From 30d60b9c610845d20e44cb667e19afa2b09771e6 Mon Sep 17 00:00:00 2001 From: "pg.yang" Date: Sun, 31 Mar 2024 20:13:03 +0800 Subject: [PATCH 001/114] Update Jedis 4.x plugin to support Sharding and Cluster models. (#677) --- CHANGES.md | 1 + .../v4/AbstractConnectionInterceptor.java | 8 +- .../v4/ConnectionConstructorInterceptor.java | 4 +- .../jedis/v4/ConnectionInformation.java | 26 ++++ ...nectionProviderConstructorInterceptor.java | 43 +++++++ ...ctionProviderGetConnectionInterceptor.java | 60 ++++++++++ .../jedis/v4/JedisMethodInterceptor.java | 8 +- .../ConnectionProviderInstrumentation.java | 81 +++++++++++++ .../src/main/resources/skywalking-plugin.def | 3 +- .../config/expectedData.yaml | 113 +++++++++++++++++- .../jedis-4.x-scenario/configuration.yml | 19 +++ .../jedis/controller/CaseController.java | 32 ++++- .../jedis/controller/ClusterExecutor.java | 42 +++++++ .../jedis/controller/ShardingExecutor.java | 42 +++++++ .../jedis-4.x-scenario/support-version.list | 4 +- 15 files changed, 478 insertions(+), 8 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionInformation.java create mode 100644 apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderGetConnectionInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/ConnectionProviderInstrumentation.java create mode 100644 test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ClusterExecutor.java create mode 100644 test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ShardingExecutor.java diff --git a/CHANGES.md b/CHANGES.md index 5627ea6ad0..eef33563e1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Release Notes. * Fix a bug in Spring Cloud Gateway if HttpClientFinalizer#send does not invoke, the span created at NettyRoutingFilterInterceptor can not stop. * Fix not tracing in HttpClient v5 when HttpHost(arg[0]) is null but `RoutingSupport#determineHost` works. * Support across thread tracing for SOFA-RPC. +* Update Jedis 4.x plugin to support Sharding and Cluster models. #### Documentation * Update docs to describe `expired-plugins`. diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/AbstractConnectionInterceptor.java b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/AbstractConnectionInterceptor.java index 79f2f15858..a1a8a16225 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/AbstractConnectionInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/AbstractConnectionInterceptor.java @@ -18,6 +18,7 @@ package org.apache.skywalking.apm.plugin.jedis.v4; import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.StringTag; import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; @@ -39,6 +40,8 @@ public abstract class AbstractConnectionInterceptor implements InstanceMethodsAr private static final String CACHE_TYPE = "Redis"; + private static final StringTag TAG_ARGS = new StringTag("actual_target"); + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { Iterator iterator = getCommands(allArguments); @@ -49,12 +52,15 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr // Use lowercase to make config compatible with jedis-2.x-3.x plugin // Refer to `plugin.jedis.operation_mapping_read`, `plugin.jedis.operation_mapping_write` config item in agent.config String cmd = protocolCommand == null ? UNKNOWN : protocolCommand.toLowerCase(); - String peer = String.valueOf(objInst.getSkyWalkingDynamicField()); + ConnectionInformation connectionData = (ConnectionInformation) objInst.getSkyWalkingDynamicField(); + // Use cluster information to adapt Virtual Cache if exists, otherwise use real server host + String peer = StringUtil.isBlank(connectionData.getClusterNodes()) ? connectionData.getActualTarget() : connectionData.getClusterNodes(); AbstractSpan span = ContextManager.createExitSpan("Jedis/" + cmd, peer); span.setComponent(ComponentsDefine.JEDIS); readKeyIfNecessary(iterator).ifPresent(key -> Tags.CACHE_KEY.set(span, key)); Tags.CACHE_CMD.set(span, cmd); Tags.CACHE_TYPE.set(span, CACHE_TYPE); + TAG_ARGS.set(span, connectionData.getActualTarget()); parseOperation(cmd).ifPresent(op -> Tags.CACHE_OP.set(span, op)); SpanLayer.asCache(span); } diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java index 825042613d..550db0072d 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java @@ -26,6 +26,8 @@ public class ConnectionConstructorInterceptor implements InstanceConstructorInte @Override public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { HostAndPort hostAndPort = ((DefaultJedisSocketFactory) allArguments[0]).getHostAndPort(); - objInst.setSkyWalkingDynamicField(hostAndPort.getHost() + ":" + hostAndPort.getPort()); + ConnectionInformation connectionData = new ConnectionInformation(); + connectionData.setActualTarget(hostAndPort.toString()); + objInst.setSkyWalkingDynamicField(connectionData); } } diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionInformation.java b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionInformation.java new file mode 100644 index 0000000000..002deff4fc --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionInformation.java @@ -0,0 +1,26 @@ +/* + * 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.jedis.v4; + +import lombok.Data; + +@Data +public class ConnectionInformation { + private String clusterNodes; + private String actualTarget; +} diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderConstructorInterceptor.java new file mode 100644 index 0000000000..21939a62e9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderConstructorInterceptor.java @@ -0,0 +1,43 @@ +/* + * 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.jedis.v4; + +import java.util.Collection; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.util.StringUtil; +import redis.clients.jedis.HostAndPort; + +public class ConnectionProviderConstructorInterceptor implements InstanceConstructorInterceptor { + @Override + public void onConstruct(final EnhancedInstance objInst, final Object[] allArguments) throws Throwable { + if (objInst.getSkyWalkingDynamicField() != null) { + return; + } + Object arg = allArguments[0]; + if (arg instanceof Collection) { + Collection collection = (Collection) arg; + final String[] array = collection.stream().map(Object::toString).toArray(String[]::new); + objInst.setSkyWalkingDynamicField(StringUtil.join(',', array)); + } + if (arg instanceof HostAndPort) { + objInst.setSkyWalkingDynamicField(arg.toString()); + } + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderGetConnectionInterceptor.java b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderGetConnectionInterceptor.java new file mode 100644 index 0000000000..12409de61d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderGetConnectionInterceptor.java @@ -0,0 +1,60 @@ +/* + * 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.jedis.v4; + +import java.lang.reflect.Method; +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; + +public class ConnectionProviderGetConnectionInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] argumentsTypes, + final MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] argumentsTypes, + final Object ret) throws Throwable { + if (ret instanceof EnhancedInstance) { + EnhancedInstance connection = (EnhancedInstance) ret; + if (connection.getSkyWalkingDynamicField() != null + && connection.getSkyWalkingDynamicField() instanceof ConnectionInformation) { + ((ConnectionInformation) connection.getSkyWalkingDynamicField()).setClusterNodes( + (String) objInst.getSkyWalkingDynamicField()); + } + } + return ret; + } + + @Override + public void handleMethodException(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] argumentsTypes, + final Throwable t) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisMethodInterceptor.java index 26175616e0..dcf181b3e5 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisMethodInterceptor.java @@ -18,6 +18,7 @@ package org.apache.skywalking.apm.plugin.jedis.v4; import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.StringTag; import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; @@ -27,18 +28,23 @@ import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import java.lang.reflect.Method; +import org.apache.skywalking.apm.util.StringUtil; public class JedisMethodInterceptor implements InstanceMethodsAroundInterceptor { + private static final StringTag TAG_ARGS = new StringTag("actual_target"); @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { - String peer = String.valueOf(objInst.getSkyWalkingDynamicField()); + final ConnectionInformation connectionData = (ConnectionInformation) objInst.getSkyWalkingDynamicField(); + // Use cluster information to adapt Virtual Cache if exists, otherwise use real server host + String peer = StringUtil.isBlank(connectionData.getClusterNodes()) ? connectionData.getActualTarget() : connectionData.getClusterNodes(); AbstractSpan span = ContextManager.createExitSpan("Jedis/" + method.getName(), peer); span.setComponent(ComponentsDefine.JEDIS); SpanLayer.asCache(span); Tags.CACHE_TYPE.set(span, "Redis"); Tags.CACHE_CMD.set(span, "BATCH_EXECUTE"); + TAG_ARGS.set(span, connectionData.getActualTarget()); } @Override diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/ConnectionProviderInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/ConnectionProviderInstrumentation.java new file mode 100644 index 0000000000..d376fb3d6a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/ConnectionProviderInstrumentation.java @@ -0,0 +1,81 @@ +/* + * 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.jedis.v4.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.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.hasSuperType; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch; + +public class ConnectionProviderInstrumentation extends AbstractWitnessInstrumentation { + + private static final String ENHANCE_INTERFACE = "redis.clients.jedis.providers.ConnectionProvider"; + private static final String CONNECTION_PROVIDER_CONSTRUCTION_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.jedis.v4.ConnectionProviderConstructorInterceptor"; + private static final String CONNECTION_PROVIDER_GET_CONNECTION_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.jedis.v4.ConnectionProviderGetConnectionInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return byHierarchyMatch(ENHANCE_INTERFACE); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return ElementMatchers.takesArgument(0, named("redis.clients.jedis.HostAndPort")) + .or(ElementMatchers.takesArgument(0, hasSuperType(named("java.util.Collection")))); + } + + @Override + public String getConstructorInterceptor() { + return CONNECTION_PROVIDER_CONSTRUCTION_INTERCEPT_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("getConnection"); + } + + @Override + public String getMethodsInterceptor() { + return CONNECTION_PROVIDER_GET_CONNECTION_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/resources/skywalking-plugin.def index a226a135b5..ae23cce498 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/resources/skywalking-plugin.def @@ -16,4 +16,5 @@ jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.ConnectionInstrumentation jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.PipelineInstrumentation -jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.TransactionConstructorInstrumentation \ No newline at end of file +jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.TransactionConstructorInstrumentation +jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.ConnectionProviderInstrumentation diff --git a/test/plugin/scenarios/jedis-4.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/jedis-4.x-scenario/config/expectedData.yaml index 6be161a8b8..14e3547916 100644 --- a/test/plugin/scenarios/jedis-4.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/jedis-4.x-scenario/config/expectedData.yaml @@ -36,6 +36,7 @@ segmentItems: - {key: cache.key, value: a} - {key: cache.cmd, value: set} - {key: cache.type, value: Redis} + - {key: actual_target, value: 'redis-server:6379'} - {key: cache.op, value: write} - operationName: Jedis/get operationId: 0 @@ -53,6 +54,7 @@ segmentItems: - {key: cache.key, value: a} - {key: cache.cmd, value: get} - {key: cache.type, value: Redis} + - {key: actual_target, value: 'redis-server:6379'} - {key: cache.op, value: read} - operationName: Jedis/del operationId: 0 @@ -70,6 +72,7 @@ segmentItems: - {key: cache.key, value: a} - {key: cache.cmd, value: del} - {key: cache.type, value: Redis} + - {key: actual_target, value: 'redis-server:6379'} - {key: cache.op, value: write} - operationName: Jedis/syncAndReturnAll operationId: 0 @@ -86,6 +89,7 @@ segmentItems: tags: - {key: cache.type, value: Redis} - {key: cache.cmd, value: BATCH_EXECUTE} + - {key: actual_target, value: 'redis-server:6379'} - operationName: Jedis/exec operationId: 0 parentSpanId: 0 @@ -101,6 +105,7 @@ segmentItems: tags: - {key: cache.type, value: Redis} - {key: cache.cmd, value: BATCH_EXECUTE} + - {key: actual_target, value: 'redis-server:6379'} - operationName: Jedis/discard operationId: 0 parentSpanId: 0 @@ -116,6 +121,7 @@ segmentItems: tags: - {key: cache.type, value: Redis} - {key: cache.cmd, value: BATCH_EXECUTE} + - {key: actual_target, value: 'redis-server:6379'} - operationName: Jedis/xadd operationId: 0 parentSpanId: 0 @@ -132,6 +138,7 @@ segmentItems: - {key: cache.key, value: abc} - {key: cache.cmd, value: xadd} - {key: cache.type, value: Redis} + - {key: actual_target, value: 'redis-server:6379'} - {key: cache.op, value: write} - operationName: Jedis/xread operationId: 0 @@ -148,6 +155,7 @@ segmentItems: tags: - {key: cache.cmd, value: xread} - {key: cache.type, value: Redis} + - {key: actual_target, value: 'redis-server:6379'} - {key: cache.op, value: read} - operationName: Jedis/xdel operationId: 0 @@ -165,6 +173,109 @@ segmentItems: - {key: cache.key, value: abc} - {key: cache.cmd, value: xdel} - {key: cache.type, value: Redis} + - {key: actual_target, value: 'redis-server:6379'} + - {key: cache.op, value: write} + - operationName: Jedis/set + parentSpanId: 0 + spanId: 10 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 30 + isError: false + spanType: Exit + peer: redis-server:6379,redis-server:6379 + skipAnalysis: false + tags: + - {key: cache.key, value: x} + - {key: cache.cmd, value: set} + - {key: cache.type, value: Redis} + - {key: actual_target, value: 'redis-server:6379'} + - {key: cache.op, value: write} + - operationName: Jedis/get + parentSpanId: 0 + spanId: 11 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 30 + isError: false + spanType: Exit + peer: redis-server:6379,redis-server:6379 + skipAnalysis: false + tags: + - {key: cache.key, value: x} + - {key: cache.cmd, value: get} + - {key: cache.type, value: Redis} + - {key: actual_target, value: 'redis-server:6379'} + - {key: cache.op, value: read} + - operationName: Jedis/del + parentSpanId: 0 + spanId: 12 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 30 + isError: false + spanType: Exit + peer: redis-server:6379,redis-server:6379 + skipAnalysis: false + tags: + - {key: cache.key, value: x} + - {key: cache.cmd, value: del} + - {key: cache.type, value: Redis} + - {key: actual_target, value: 'redis-server:6379'} + - {key: cache.op, value: write} + - operationName: Jedis/set + parentSpanId: 0 + spanId: 13 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 30 + isError: false + spanType: Exit + peer: redis-cluster-m3:6379,redis-cluster-m2:6379,redis-cluster-m1:6379 + skipAnalysis: false + tags: + - {key: cache.key, value: x} + - {key: cache.cmd, value: set} + - {key: cache.type, value: Redis} + - {key: actual_target, value: not blank } + - {key: cache.op, value: write} + - operationName: Jedis/get + parentSpanId: 0 + spanId: 14 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 30 + isError: false + spanType: Exit + peer: redis-cluster-m3:6379,redis-cluster-m2:6379,redis-cluster-m1:6379 + skipAnalysis: false + tags: + - {key: cache.key, value: x} + - {key: cache.cmd, value: get} + - {key: cache.type, value: Redis} + - {key: actual_target, value: not blank} + - {key: cache.op, value: read} + - operationName: Jedis/del + parentSpanId: 0 + spanId: 15 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 30 + isError: false + spanType: Exit + peer: redis-cluster-m3:6379,redis-cluster-m2:6379,redis-cluster-m1:6379 + skipAnalysis: false + tags: + - {key: cache.key, value: x} + - {key: cache.cmd, value: del} + - {key: cache.type, value: Redis} + - {key: actual_target, value: not blank } - {key: cache.op, value: write} - operationName: GET:/jedis-scenario/case/jedis-scenario operationId: 0 @@ -181,4 +292,4 @@ segmentItems: tags: - {key: url, value: 'http://localhost:8080/jedis-scenario/case/jedis-scenario'} - {key: http.method, value: GET} - - {key: http.status_code, value: '200'} \ No newline at end of file + - {key: http.status_code, value: '200'} diff --git a/test/plugin/scenarios/jedis-4.x-scenario/configuration.yml b/test/plugin/scenarios/jedis-4.x-scenario/configuration.yml index 79dfda5c0b..e340adec0d 100644 --- a/test/plugin/scenarios/jedis-4.x-scenario/configuration.yml +++ b/test/plugin/scenarios/jedis-4.x-scenario/configuration.yml @@ -21,8 +21,27 @@ startScript: ./bin/startup.sh environment: - REDIS_HOST=redis-server - REDIS_PORT=6379 + - REDIS_CLUSTER_M1_HOST=redis-cluster-m1 + - REDIS_CLUSTER_M1_PORT=6379 + - REDIS_CLUSTER_M2_HOST=redis-cluster-m2 + - REDIS_CLUSTER_M2_PORT=6379 + - REDIS_CLUSTER_M3_HOST=redis-cluster-m3 + - REDIS_CLUSTER_M3_PORT=6379 + dependencies: redis-server: image: redis:7.0.4 hostname: redis-server + redis-cluster-m1: + image: redis:7.2.4 + hostname: redis-cluster-m1 + command: sh -c " printf '%s\\n' 'port 6379'>> /etc/redis.conf && printf '%s\\n' 'cluster-enabled yes'>> /etc/redis.conf && printf '%s\\n' 'cluster-config-file nodes.conf'>> /etc/redis.conf && printf '%s\\n' 'nohup redis-server /etc/redis.conf>>/tmp/redis.log &' >> /tmp/start-redis.sh && printf '%s\\n' 'while true; do printf yes | redis-cli --cluster create redis-cluster-m1:6379 redis-cluster-m2:6379 redis-cluster-m3:6379 --cluster-replicas 0 && break; done ' >> /tmp/start-redis.sh && printf '%s\\n' 'tail -f /tmp/redis.log' >> /tmp/start-redis.sh && sh /tmp/start-redis.sh" + redis-cluster-m2: + image: redis:7.2.4 + hostname: redis-cluster-m2 + command: sh -c " printf '%s\\n' 'port 6379'>> /etc/redis.conf && printf '%s\\n' 'cluster-enabled yes'>> /etc/redis.conf && printf '%s\\n' 'cluster-config-file nodes.conf'>> /etc/redis.conf && printf '%s\\n' 'nohup redis-server /etc/redis.conf>>/tmp/redis.log &' >> /tmp/start-redis.sh && printf '%s\\n' 'while true; do printf yes | redis-cli --cluster create redis-cluster-m1:6379 redis-cluster-m2:6379 redis-cluster-m3:6379 --cluster-replicas 0 && break; done ' >> /tmp/start-redis.sh && printf '%s\\n' 'tail -f /tmp/redis.log' >> /tmp/start-redis.sh && sh /tmp/start-redis.sh" + redis-cluster-m3: + image: redis:7.2.4 + hostname: redis-cluster-m3 + command: sh -c " printf '%s\\n' 'port 6379'>> /etc/redis.conf && printf '%s\\n' 'cluster-enabled yes'>> /etc/redis.conf && printf '%s\\n' 'cluster-config-file nodes.conf'>> /etc/redis.conf && printf '%s\\n' 'nohup redis-server /etc/redis.conf>>/tmp/redis.log &' >> /tmp/start-redis.sh && printf '%s\\n' 'while true; do printf yes | redis-cli --cluster create redis-cluster-m1:6379 redis-cluster-m2:6379 redis-cluster-m3:6379 --cluster-replicas 0 && break; done ' >> /tmp/start-redis.sh && printf '%s\\n' 'tail -f /tmp/redis.log' >> /tmp/start-redis.sh && sh /tmp/start-redis.sh" diff --git a/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/CaseController.java b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/CaseController.java index a7f570960a..fd7999060a 100644 --- a/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/CaseController.java +++ b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/CaseController.java @@ -18,10 +18,13 @@ package org.apache.skywalking.apm.testcase.jedis.controller; +import java.util.Arrays; +import java.util.HashSet; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; +import redis.clients.jedis.HostAndPort; @RestController @RequestMapping("/case") @@ -35,6 +38,21 @@ public class CaseController { @Value("${redis.port:6379}") private Integer redisPort; + @Value("${redis.cluster.m1.host:127.0.0.1}") + private String redisClusterM1Host; + @Value("${redis.cluster.m1.port:6379}") + private Integer redisClusterM1Port; + + @Value("${redis.cluster.m2.host:127.0.0.1}") + private String redisClusterM2Host; + @Value("${redis.cluster.m2.port:6379}") + private Integer redisClusterM2Port; + + @Value("${redis.cluster.m3.host:127.0.0.1}") + private String redisClusterM3Host; + @Value("${redis.cluster.m3.port:6379}") + private Integer redisClusterM3Port; + @RequestMapping("/jedis-scenario") @ResponseBody public String testcase() throws Exception { @@ -43,7 +61,6 @@ public String testcase() throws Exception { command.get("a"); command.del("a"); } - try (RedisPipelineCommandExecutor command = new RedisPipelineCommandExecutor(redisHost, redisPort)) { command.pipelineExecute(); } @@ -55,7 +72,18 @@ public String testcase() throws Exception { try (RedisStreamCommandExecutor executor = new RedisStreamCommandExecutor(redisHost, redisPort)) { executor.exec(); } - + try (ShardingExecutor shardingExecutor = new ShardingExecutor( + Arrays.asList(new HostAndPort(redisHost, redisPort), new HostAndPort(redisHost, redisPort)))) { + shardingExecutor.exec(); + } + try (ClusterExecutor clusterExecutor = new ClusterExecutor(new HashSet<>( + Arrays.asList( + new HostAndPort(redisClusterM1Host, redisClusterM1Port), + new HostAndPort(redisClusterM2Host, redisClusterM2Port), + new HostAndPort(redisClusterM3Host, redisClusterM3Port) + )))) { + clusterExecutor.exec(); + } return SUCCESS; } diff --git a/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ClusterExecutor.java b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ClusterExecutor.java new file mode 100644 index 0000000000..8e9293e04e --- /dev/null +++ b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ClusterExecutor.java @@ -0,0 +1,42 @@ +/* + * 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.testcase.jedis.controller; + +import java.util.Set; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisCluster; + +public class ClusterExecutor implements AutoCloseable { + + private final JedisCluster jedisCluster; + + public ClusterExecutor(Set jedisClusterNodes) { + this.jedisCluster = new JedisCluster(jedisClusterNodes); + } + + public void exec() { + jedisCluster.set("x", "1"); + jedisCluster.get("x"); + jedisCluster.del("x"); + } + + public void close() { + this.jedisCluster.close(); + } +} diff --git a/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ShardingExecutor.java b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ShardingExecutor.java new file mode 100644 index 0000000000..482d942837 --- /dev/null +++ b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ShardingExecutor.java @@ -0,0 +1,42 @@ +/* + * 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.testcase.jedis.controller; + +import java.util.List; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.JedisSharding; + +public class ShardingExecutor implements AutoCloseable { + private JedisSharding jedisSharding; + + public ShardingExecutor(List hostAndPorts) { + this.jedisSharding = new JedisSharding(hostAndPorts); + } + + public void exec() { + jedisSharding.set("x", "1"); + jedisSharding.get("x"); + jedisSharding.del("x"); + } + + public void close() { + jedisSharding.close(); + } + +} diff --git a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list b/test/plugin/scenarios/jedis-4.x-scenario/support-version.list index 209481d5b8..31258966c3 100644 --- a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list +++ b/test/plugin/scenarios/jedis-4.x-scenario/support-version.list @@ -14,6 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +4.4.6 +4.3.2 4.2.3 4.1.1 -4.0.1 \ No newline at end of file +4.0.1 From eb1041675cafb31dcc8da1fc0a45bc796d5b912c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Sun, 31 Mar 2024 21:38:08 +0800 Subject: [PATCH 002/114] Release 9.2.0 begin 9.3.0 dev (#678) --- CHANGES.md | 20 +++----------- .../apm-toolkit-kafka/pom.xml | 2 +- .../apm-toolkit-log4j-1.x/pom.xml | 2 +- .../apm-toolkit-log4j-2.x/pom.xml | 2 +- .../apm-toolkit-logback-1.x/pom.xml | 2 +- .../apm-toolkit-meter/pom.xml | 2 +- .../apm-toolkit-micrometer-1.10/pom.xml | 2 +- .../apm-toolkit-micrometer-registry/pom.xml | 2 +- .../apm-toolkit-opentracing/pom.xml | 2 +- .../apm-toolkit-trace/pom.xml | 2 +- .../apm-toolkit-webflux/pom.xml | 2 +- apm-application-toolkit/pom.xml | 2 +- apm-commons/apm-datacarrier/pom.xml | 2 +- apm-commons/apm-util/pom.xml | 2 +- apm-commons/pom.xml | 2 +- apm-protocol/apm-network/pom.xml | 2 +- apm-protocol/pom.xml | 2 +- apm-sniffer/apm-agent-core/pom.xml | 2 +- apm-sniffer/apm-agent/pom.xml | 2 +- .../activemq-5.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/aerospike-plugin/pom.xml | 2 +- .../apm-armeria-0.84.x-plugin/pom.xml | 2 +- .../apm-armeria-0.85.x-plugin/pom.xml | 2 +- .../apm-armeria-1.0.x-plugin/pom.xml | 2 +- .../apm-armeria-plugins/pom.xml | 2 +- .../asynchttpclient-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/avro-plugin/pom.xml | 2 +- .../baidu-brpc-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/baidu-brpc-plugin/pom.xml | 2 +- .../apm-sdk-plugin/canal-1.x-plugin/pom.xml | 2 +- .../cassandra-java-driver-3.x-plugin/pom.xml | 2 +- .../clickhouse-0.3.1-plugin/pom.xml | 2 +- .../clickhouse-0.3.2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/cxf-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/dbcp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/druid-1.x-plugin/pom.xml | 2 +- .../dubbo-2.7.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml | 2 +- .../dubbo-3.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-3.x-plugin/pom.xml | 2 +- .../dubbo-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-plugin/pom.xml | 2 +- .../elastic-job-2.x-plugin/pom.xml | 2 +- .../elasticjob-3.x-plugin/pom.xml | 2 +- .../elasticsearch-5.x-plugin/pom.xml | 2 +- .../elasticsearch-6.x-plugin/pom.xml | 2 +- .../elasticsearch-7.x-plugin/pom.xml | 2 +- .../elasticsearch-common/pom.xml | 2 +- .../feign-default-http-9.x-plugin/pom.xml | 2 +- .../finagle-6.25.x-plugin/pom.xml | 2 +- .../graphql-12.x-15.x-plugin/pom.xml | 2 +- .../graphql-16plus-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-8.x-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/graphql-plugin/pom.xml | 2 +- .../grizzly-2.3.x-4.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/grpc-1.x-plugin/pom.xml | 2 +- .../guava-eventbus-plugin/pom.xml | 2 +- .../apm-sdk-plugin/h2-1.x-plugin/pom.xml | 2 +- .../hbase-1.x-2.x-plugin/pom.xml | 2 +- .../hikaricp-3.x-4.x-plugin/pom.xml | 2 +- .../httpClient-4.x-plugin/pom.xml | 2 +- .../httpasyncclient-4.x-plugin/pom.xml | 2 +- .../httpclient-3.x-plugin/pom.xml | 2 +- .../httpclient-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/httpclient-commons/pom.xml | 2 +- .../hutool-http-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/hutool-plugins/pom.xml | 2 +- .../apm-sdk-plugin/hystrix-1.x-plugin/pom.xml | 2 +- .../influxdb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jdbc-commons/pom.xml | 2 +- .../jedis-2.x-3.x-plugin/pom.xml | 2 +- .../jedis-plugins/jedis-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jedis-plugins/pom.xml | 2 +- .../apm-sdk-plugin/jersey-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jersey-3.x-plugin/pom.xml | 2 +- .../jetty-client-11.x-plugin/pom.xml | 2 +- .../jetty-client-9.0-plugin/pom.xml | 2 +- .../jetty-client-9.x-plugin/pom.xml | 2 +- .../jetty-server-11.x-plugin/pom.xml | 2 +- .../jetty-server-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jetty-plugin/pom.xml | 2 +- .../jetty-thread-pool-plugin/pom.xml | 2 +- .../jsonrpc4j-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/kafka-commons/pom.xml | 2 +- .../apm-sdk-plugin/kafka-plugin/pom.xml | 2 +- .../kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/lettuce-5.x-plugin/pom.xml | 2 +- .../light4j-plugins/light4j-plugin/pom.xml | 2 +- .../apm-sdk-plugin/light4j-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mariadb-2.x-plugin/pom.xml | 2 +- .../micronaut-http-client-plugin/pom.xml | 2 +- .../micronaut-http-server-plugin/pom.xml | 2 +- .../apm-sdk-plugin/micronaut-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/motan-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mssql-commons/pom.xml | 2 +- .../apm-sdk-plugin/mssql-jdbc-plugin/pom.xml | 2 +- .../mssql-jtds-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-6.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-common/pom.xml | 2 +- .../nats-2.14.x-2.15.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/neo4j-4.x-plugin/pom.xml | 2 +- .../netty-socketio-plugin/pom.xml | 2 +- .../nutz-plugins/http-1.x-plugin/pom.xml | 2 +- .../mvc-annotation-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/nutz-plugins/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-common/pom.xml | 2 +- .../apm-sdk-plugin/play-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-sdk-plugin/pom.xml | 2 +- .../postgresql-8.x-plugin/pom.xml | 2 +- .../pulsar-2.2-2.7-plugin/pom.xml | 2 +- .../pulsar-2.8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/pulsar-common/pom.xml | 2 +- .../apm-sdk-plugin/quasar-plugin/pom.xml | 2 +- .../apm-sdk-plugin/rabbitmq-plugin/pom.xml | 2 +- .../redisson-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/resteasy-plugin/pom.xml | 2 +- .../resteasy-server-3.x-plugin/pom.xml | 2 +- .../resteasy-server-4.x-plugin/pom.xml | 2 +- .../resteasy-server-6.x-plugin/pom.xml | 2 +- .../rocketMQ-3.x-plugin/pom.xml | 2 +- .../rocketMQ-4.x-plugin/pom.xml | 2 +- .../rocketMQ-5.x-plugin/pom.xml | 2 +- .../rocketMQ-client-java-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/servicecomb-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../shardingsphere-plugins/pom.xml | 2 +- .../sharding-sphere-3.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.0.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.1.0-plugin/pom.xml | 2 +- .../sharding-sphere-5.0.0-plugin/pom.xml | 2 +- .../apm-sdk-plugin/sofarpc-plugin/pom.xml | 2 +- .../apm-sdk-plugin/solrj-7.x-plugin/pom.xml | 2 +- .../async-annotation-plugin/pom.xml | 2 +- .../concurrent-util-4.x-plugin/pom.xml | 2 +- .../spring-plugins/core-patch/pom.xml | 2 +- .../mvc-annotation-3.x-plugin/pom.xml | 2 +- .../mvc-annotation-4.x-plugin/pom.xml | 2 +- .../mvc-annotation-5.x-plugin/pom.xml | 2 +- .../mvc-annotation-commons/pom.xml | 2 +- .../apm-sdk-plugin/spring-plugins/pom.xml | 2 +- .../resttemplate-3.x-plugin/pom.xml | 2 +- .../resttemplate-4.x-plugin/pom.xml | 2 +- .../resttemplate-commons/pom.xml | 2 +- .../scheduled-annotation-plugin/pom.xml | 2 +- .../spring-cloud/netflix-plugins/pom.xml | 2 +- .../spring-cloud-feign-1.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-cloud/pom.xml | 2 +- .../spring-cloud-feign-2.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-commons/pom.xml | 2 +- .../spring-kafka-1.x-plugin/pom.xml | 2 +- .../spring-kafka-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../spymemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/struts2-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/thrift-plugin/pom.xml | 2 +- .../apm-sdk-plugin/tomcat-10x-plugin/pom.xml | 2 +- .../tomcat-7.x-8.x-plugin/pom.xml | 2 +- .../tomcat-thread-pool-plugin/pom.xml | 2 +- .../apm-sdk-plugin/undertow-plugins/pom.xml | 2 +- .../undertow-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/vertx-plugins/pom.xml | 2 +- .../vertx-core-3.x-plugin/pom.xml | 2 +- .../vertx-core-4.x-plugin/pom.xml | 2 +- .../websphere-liberty-23.x-plugin/pom.xml | 2 +- .../xmemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-test-tools/pom.xml | 2 +- .../apm-toolkit-kafka-activation/pom.xml | 2 +- .../apm-toolkit-log4j-1.x-activation/pom.xml | 2 +- .../apm-toolkit-log4j-2.x-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-logging-common/pom.xml | 2 +- .../apm-toolkit-meter-activation/pom.xml | 2 +- .../apm-toolkit-micrometer-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-trace-activation/pom.xml | 2 +- .../apm-toolkit-webflux-activation/pom.xml | 2 +- apm-sniffer/apm-toolkit-activation/pom.xml | 2 +- .../jdk-forkjoinpool-plugin/pom.xml | 2 +- .../bootstrap-plugins/jdk-http-plugin/pom.xml | 2 +- .../jdk-threading-plugin/pom.xml | 2 +- .../jdk-threadpool-plugin/pom.xml | 2 +- apm-sniffer/bootstrap-plugins/pom.xml | 2 +- apm-sniffer/bytebuddy-patch/pom.xml | 2 +- .../impala-jdbc-2.6.x-plugin/pom.xml | 2 +- apm-sniffer/expired-plugins/pom.xml | 2 +- .../customize-enhance-plugin/pom.xml | 2 +- .../ehcache-2.x-plugin/pom.xml | 2 +- .../fastjson-1.2.x-plugin/pom.xml | 2 +- .../gson-2.8.x-plugin/pom.xml | 2 +- .../guava-cache-plugin/pom.xml | 2 +- .../jackson-2.x-plugin/pom.xml | 2 +- .../kotlin-coroutine-plugin/pom.xml | 2 +- .../mybatis-3.x-plugin/pom.xml | 2 +- .../nacos-client-2.x-plugin/pom.xml | 2 +- .../netty-http-4.1.x-plugin/pom.xml | 2 +- .../mvc-annotation-6.x-plugin/pom.xml | 2 +- .../gateway-2.0.x-plugin/pom.xml | 2 +- .../gateway-2.1.x-plugin/pom.xml | 2 +- .../gateway-3.x-plugin/pom.xml | 2 +- .../gateway-4.x-plugin/pom.xml | 2 +- .../optional-spring-cloud/pom.xml | 2 +- .../optional-spring-plugins/pom.xml | 2 +- .../resttemplate-6.x-plugin/pom.xml | 2 +- .../spring-annotation-plugin/pom.xml | 2 +- .../spring-tx-plugin/pom.xml | 2 +- .../spring-webflux-5.x-plugin/pom.xml | 2 +- .../spring-webflux-6.x-plugin/pom.xml | 2 +- apm-sniffer/optional-plugins/pom.xml | 2 +- .../quartz-scheduler-2.x-plugin/pom.xml | 2 +- .../sentinel-1.x-plugin/pom.xml | 2 +- .../shenyu-2.4.x-plugin/pom.xml | 2 +- .../trace-ignore-plugin/pom.xml | 2 +- .../trace-sampler-cpu-policy-plugin/pom.xml | 2 +- .../zookeeper-3.4.x-plugin/pom.xml | 2 +- .../kafka-config-extension/pom.xml | 2 +- .../kafka-reporter-plugin/pom.xml | 2 +- apm-sniffer/optional-reporter-plugins/pom.xml | 2 +- apm-sniffer/pom.xml | 2 +- changes/changes-9.2.0.md | 27 +++++++++++++++++++ pom.xml | 2 +- 234 files changed, 262 insertions(+), 249 deletions(-) create mode 100644 changes/changes-9.2.0.md diff --git a/CHANGES.md b/CHANGES.md index eef33563e1..ce908f8278 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,29 +2,15 @@ Changes by Version ================== Release Notes. -9.2.0 +9.3.0 ------------------ -* Fix NoSuchMethodError in mvc-annotation-commons and change deprecated method. -* Fix forkjoinpool plugin in JDK11. -* Support for tracing spring-cloud-gateway 4.x in gateway-4.x-plugin. -* Fix re-transform bug when plugin enhanced class proxy parent method. -* Fix error HTTP status codes not recording as SLA failures in Vert.x plugins. -* Support for HttpExchange request tracing. -* Support tracing for async producing, batch sync consuming, and batch async consuming in rocketMQ-client-java-5.x-plugin. -* Convert the Redisson span into an async span. -* Rename system env name from `sw_plugin_kafka_producer_config` to `SW_PLUGIN_KAFKA_PRODUCER_CONFIG`. -* Support for ActiveMQ-Artemis messaging tracing. -* Archive the expired plugins `impala-jdbc-2.6.x-plugin`. -* Fix a bug in Spring Cloud Gateway if HttpClientFinalizer#send does not invoke, the span created at NettyRoutingFilterInterceptor can not stop. -* Fix not tracing in HttpClient v5 when HttpHost(arg[0]) is null but `RoutingSupport#determineHost` works. -* Support across thread tracing for SOFA-RPC. -* Update Jedis 4.x plugin to support Sharding and Cluster models. + #### Documentation * Update docs to describe `expired-plugins`. -All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/204?closed=1) +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) ------------------ Find change logs of all versions [here](changes). diff --git a/apm-application-toolkit/apm-toolkit-kafka/pom.xml b/apm-application-toolkit/apm-toolkit-kafka/pom.xml index 9f612c228b..6edc74c7fb 100644 --- a/apm-application-toolkit/apm-toolkit-kafka/pom.xml +++ b/apm-application-toolkit/apm-toolkit-kafka/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml index 893f062e28..057ac5676d 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml index 09c604acd7..e334a37b0e 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml index 1ee1242ba0..2484061d6e 100644 --- a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-meter/pom.xml b/apm-application-toolkit/apm-toolkit-meter/pom.xml index 91ed42b70e..c8453f9f17 100644 --- a/apm-application-toolkit/apm-toolkit-meter/pom.xml +++ b/apm-application-toolkit/apm-toolkit-meter/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml index 98b6dec2f9..b9c1a09c78 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml index d2882e4c1d..5554bbf8a0 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml index d517cf9ba0..5bfe3f8f26 100644 --- a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml +++ b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-trace/pom.xml b/apm-application-toolkit/apm-toolkit-trace/pom.xml index a97add2ba6..b942b7afb5 100644 --- a/apm-application-toolkit/apm-toolkit-trace/pom.xml +++ b/apm-application-toolkit/apm-toolkit-trace/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-webflux/pom.xml b/apm-application-toolkit/apm-toolkit-webflux/pom.xml index 1e0d76778f..3a74445896 100644 --- a/apm-application-toolkit/apm-toolkit-webflux/pom.xml +++ b/apm-application-toolkit/apm-toolkit-webflux/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/pom.xml b/apm-application-toolkit/pom.xml index 3610a77e88..03e7a72ec0 100644 --- a/apm-application-toolkit/pom.xml +++ b/apm-application-toolkit/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 apm-application-toolkit diff --git a/apm-commons/apm-datacarrier/pom.xml b/apm-commons/apm-datacarrier/pom.xml index 8167793d82..899bcb889c 100644 --- a/apm-commons/apm-datacarrier/pom.xml +++ b/apm-commons/apm-datacarrier/pom.xml @@ -21,7 +21,7 @@ java-agent-commons org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/apm-util/pom.xml b/apm-commons/apm-util/pom.xml index f0c0f422d6..b87ce0fdd3 100644 --- a/apm-commons/apm-util/pom.xml +++ b/apm-commons/apm-util/pom.xml @@ -20,7 +20,7 @@ java-agent-commons org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/pom.xml b/apm-commons/pom.xml index 930dbef34e..210ef6205f 100644 --- a/apm-commons/pom.xml +++ b/apm-commons/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/apm-network/pom.xml b/apm-protocol/apm-network/pom.xml index 78086418f6..f7d68fbcbe 100644 --- a/apm-protocol/apm-network/pom.xml +++ b/apm-protocol/apm-network/pom.xml @@ -21,7 +21,7 @@ java-agent-protocol org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/pom.xml b/apm-protocol/pom.xml index c8eb4d2759..b29b3b9732 100644 --- a/apm-protocol/pom.xml +++ b/apm-protocol/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index ebea951ca8..132e2dbfd0 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-agent-core diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 2d8f73214b..d11eb7d06a 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-agent diff --git a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml index 0956d91d4f..8420d03312 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml index cc6a9f1ae2..6527e2dae4 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml index 7f9148573f..554cd600c8 100644 --- a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml index 1a31ced10b..9bda76fd4d 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml index b987bf0852..b44db06e67 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml index 3209d63d6c..3423b90100 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml index 24f68f1cbb..1ecdee4e30 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml index 7a3dcaf36e..075c51cb44 100644 --- a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml index ed69c782a8..5e6d29aac1 100644 --- a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml index 2de9d1e726..35c4df05a9 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml index a793335f55..f5d447f483 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml index c5f85346a3..b7416bc262 100644 --- a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml index 043ca5f1d1..be6fbca7ec 100644 --- a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml index dcc05354b9..b71127cd6d 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml index 00bc941f41..6e7edbe2ef 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml index 612482786a..0f056f4135 100644 --- a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml index a1c9770f77..f6326650e5 100644 --- a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml index d3fc28a30d..10e1afb8f9 100644 --- a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml index 6a04864b83..ee46e542ff 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml index d42f327a5b..8ff3bb504e 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml index 6c2fabb877..3fbd5240e3 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml index 806c76fa2d..1728372ca7 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml index c94396034b..326b3c0ca7 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml index f99b4ad833..1555484e02 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml index 6a2863e923..94bc082bf4 100644 --- a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml index 048f5ce71e..d82734c045 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml index 292485a085..6205465134 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml index 9f11bfdb3c..204b52615a 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml index c51efcdcfa..d8d15a0d32 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml index b4dee8ad78..1658b62cce 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml index 74d05bfdc3..e641e9512f 100644 --- a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml index 3ff991b40d..cc875605fa 100644 --- a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml index a2804dafcf..b56a1905e3 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml index 6c4684c0cd..7cd4ed7172 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml index 3025ff06fe..c9d0fa4de0 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml index c1f67a749c..39666ba3e1 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml index 40d94ac707..dd0f22b3fd 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml index c1f9b7129e..5c4f29668d 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml index c5fb2521d4..958782012c 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-grizzly-2.x-4.x-work-threadpool-plugin diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml index 1b188f16a9..76b32efb36 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-grpc-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml index 20d42e9f91..31109f5f26 100644 --- a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml index 1195786969..ef577b70b2 100755 --- a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml index a947f6940d..e852e6cb80 100644 --- a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-hbase-1.x-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml index 903716083c..a48229f282 100644 --- a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml index 3a10202ebd..772529e458 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-httpClient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml index 8497d83457..87656a9dbc 100644 --- a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-httpasyncclient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml index 477e9028a5..e03fcef53c 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-httpclient-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml index d5da174f16..d205761cee 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-httpclient-5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml index 69b2a387a6..e0cdc80bbe 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-httpclient-commons diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml index 042be7b679..f2d0495cc8 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ hutool-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml index 257e44f41d..3394b0092c 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml index 72b0b525a6..b4ed0b93b3 100644 --- a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml index f7aa70e074..ab281eaeb1 100644 --- a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml index 3cef466f69..a6485b4582 100755 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml index b4d2e02e57..310e07a400 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking jedis-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml index cbd586387d..1f6cc9db71 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ jedis-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml index 3180436f6d..56bf312da3 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT diff --git a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml index 225c6a178c..0f56f34dbf 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml index d5e06143e0..36070531c2 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml index 08751914d3..cde6fd5449 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml index 7df69012f8..199bc45aac 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml index 906d2d7675..8e091d09b2 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml index fdede35fcf..2f0ae53188 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml index 52a860967b..03f8740533 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml index 20f6257f02..d939bf88b5 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT jetty-plugins diff --git a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml index eceba60962..101dcaae14 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml index a31b247ed4..533e961137 100644 --- a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml index 3d37985fcd..bf86caceda 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-kafka-commons diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml index 15bcf8bcdf..c5e17d52ed 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml index 8896304707..74ee2c3c55 100644 --- a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml index b9a86f9b04..ed057fe5ef 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-lettuce-5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml index a669c6e9ef..722371d8b5 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml @@ -20,7 +20,7 @@ light4j-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml index 6af9b359fc..5d738e3b5f 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT light4j-plugins diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml index 17c2426017..05ab767ccb 100644 --- a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml index 758f5b7c3e..30b35cca03 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml index f5217fbe8b..6f3b7c80bd 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml index 04b6a26e72..931bc20085 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml index 14c0c230bf..4fb80d5e87 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml index 99adf67594..68c1ade2e2 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-mongodb-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml index 43c8648fd7..868f1d9ab7 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-mongodb-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml index 3c57658c57..51b3fec800 100644 --- a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml index a5c6aadfec..6cbcb3a4af 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml index 0802c98edc..e8da306dd9 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml index d9845d6ff1..be33212cbe 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml index 01fd51a514..babac7d15d 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml index fb21d0faff..932e2aadf6 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml index 7579e67444..fd95d69452 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml index 6aa80d8210..4ce77ba866 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml index b447f3bbaf..8ec619ea33 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml index 30857885b8..8cb025d1be 100644 --- a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml index 55a33e8286..bd80a20010 100644 --- a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml index 2148c6f271..da79858c39 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml index 1d8c46a0bc..b9ba31e760 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml index c83b08a2e7..669753f580 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT nutz-plugins diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml index 5419edf70e..770d413b09 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml index 2ec173d6dd..eca6ff770b 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml index 432652f441..ce9ce36b53 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml index 8d0ecba8d4..3881fd2396 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml index 40f8aebc8e..e5ce15cff8 100644 --- a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-play-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 1c8c1cb97c..bf07afa7a6 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking java-agent-sniffer - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-sdk-plugin diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml index bbd44aed03..46da28a309 100755 --- a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml index 13c3c9d6ae..27dbb81b6a 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml index 6b128f50a6..7f219a6086 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml index ef06531d74..ab1a87f751 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml index b34d95a9b9..a0a5219174 100644 --- a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-quasar-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml index f6a48a3415..a4ffebf7d3 100644 --- a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml index 343cbac755..2e0d14219d 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-redisson-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml index 85f23f8f7d..aca4e0a2e2 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT resteasy-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml index 066461cc65..7f911f2507 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT resteasy-server-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml index 6b216a9bec..4590d8e2ec 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT resteasy-server-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml index 822d6a5c5f..1b91053387 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT resteasy-server-6.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml index 55687939a6..72feb352bf 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml index 08f8accaf4..7b3c637a92 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml index 0c5d663df1..5669605bb4 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml index 69d049ab83..c48f2da760 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml index 7c231e0dab..9a64259d48 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml index beec444fba..71b5934e03 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ servicecomb-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml index c2f9bb6529..7f124736d2 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml index 7d8268cba3..41131a2b2d 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml index f772019ae2..3493c95e09 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml index a34ab484c2..b86c520ac5 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml index 8ebfdfc1d1..176dba0ace 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml index c87bf752fb..5a6e57662a 100644 --- a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml index 3a89801c3e..64a46cd10c 100644 --- a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml index a5e13159e5..c0484a07f1 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml index 6965f8d5fd..0c49963f86 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml index 0115d32d5a..5807a025ba 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml index 4738e506da..dfab514b02 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml index 0ccb9edfb8..0d6d45e1e4 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml index 7b2234b64b..f74cf3733c 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml @@ -19,7 +19,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml index 348d608020..eb71af642d 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml index d9a61849aa..64abfdb7eb 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT spring-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml index 3fb9d5a0f0..4814e20078 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml index 608b1b9f75..08789aa954 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml index f493560080..4976c79954 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml index 602738f418..23a5790757 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml index e783b45119..89283b1370 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT netflix-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml index c5264d7570..d11a119602 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking netflix-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-spring-cloud-feign-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml index 283b73e6ab..08afa3d3f0 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT spring-cloud diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml index 9155ab7b17..a9d0430b86 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-spring-cloud-feign-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml index 1d3911d0e1..5e48bb5251 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml index 99c8c4013c..3f06456a34 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-spring-kafka-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml index 45bb135adb..9741509279 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-spring-kafka-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml index 067bc2df0f..868bd94200 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml index 691973be6c..528735645b 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml index 0deb79662c..a44cd64c18 100644 --- a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-spymemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml index 45046d6808..b116ccd389 100644 --- a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml index 81abe91fb0..9d8692028e 100644 --- a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml index 0cda2bb576..48b7ce02ff 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml index 176db30b0a..c881962896 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml index 8db664a50b..6fc859269b 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml index 7fe5ee485a..85ad76522d 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT undertow-plugins diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml index e07b1920fd..b5abe20db9 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ undertow-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml index b2bdda708b..9e500f59ae 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml index 97d0535cea..b5818b98f3 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT vertx-plugins diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml index c011313320..e9c720d80f 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml index be902137b7..42a48a40e3 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml index 6b54ab3248..a2ba27cf03 100644 --- a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml index 21b1411836..841535f8db 100644 --- a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-xmemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml index 6400d0cca7..a008627a7a 100644 --- a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-test-tools/pom.xml b/apm-sniffer/apm-test-tools/pom.xml index 9e1dc85659..db5fa5298b 100644 --- a/apm-sniffer/apm-test-tools/pom.xml +++ b/apm-sniffer/apm-test-tools/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-test-tools diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml index f2be4b6591..5c7df0c206 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml index 55d214e1d6..1b937485b5 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml index 45190854e3..a4d7f78bbe 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml index e56f573c60..9134874b44 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml index 2c42d0ea78..85659cfb98 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml index a767d9fa99..30a272ff2c 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml index 84559dac5e..d63725b992 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml index 3b556d06d2..d0484207c1 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml index 268aa4f9ea..56a268c4a1 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml index cbdf7f0850..f56c2edf8f 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/pom.xml index 96d08926f6..f597ebabea 100644 --- a/apm-sniffer/apm-toolkit-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml index b71269dc8d..0f9790e758 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml index c7d8003e22..a1bcb92708 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml index 7cae75e919..29efafb1ae 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml index 26b48ac5d9..91799d8558 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml @@ -20,7 +20,7 @@ bootstrap-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/pom.xml b/apm-sniffer/bootstrap-plugins/pom.xml index 8601027091..bc540de6ab 100644 --- a/apm-sniffer/bootstrap-plugins/pom.xml +++ b/apm-sniffer/bootstrap-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bytebuddy-patch/pom.xml b/apm-sniffer/bytebuddy-patch/pom.xml index 4cc94f81d8..e5ec1d0cda 100644 --- a/apm-sniffer/bytebuddy-patch/pom.xml +++ b/apm-sniffer/bytebuddy-patch/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking java-agent-sniffer - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml index 8ced3f47b9..38b2880c74 100644 --- a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml +++ b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml @@ -24,7 +24,7 @@ org.apache.skywalking expired-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-impala-jdbc-2.6.x-plugin diff --git a/apm-sniffer/expired-plugins/pom.xml b/apm-sniffer/expired-plugins/pom.xml index 708f47aaa2..817506785a 100644 --- a/apm-sniffer/expired-plugins/pom.xml +++ b/apm-sniffer/expired-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml index 60bb7c115e..2c9ee683f6 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml index 13941d9d08..02c5ad33f5 100644 --- a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml index 5793a15788..f0019fa5ec 100644 --- a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-fastjson-1.x-plugin diff --git a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml index 3c45a2e5ce..8211d2e4df 100644 --- a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-gson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml index 54b4cf9a53..79cfd12796 100644 --- a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-guava-cache-plugin diff --git a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml index dda756c727..75279981da 100644 --- a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-jackson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml index a674607cf2..6c34690e6e 100644 --- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-kotlin-coroutine-plugin diff --git a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml index e1aacd4df9..b738e93ad5 100644 --- a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-mybatis-3.x-plugin diff --git a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml index 994c32e5d1..6da357f801 100644 --- a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml index 1d05a2cd07..a135366369 100644 --- a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml index 9323c57f16..ed3daad261 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml @@ -19,7 +19,7 @@ optional-spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml index 77f5a9c5ae..c483e6b29d 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-spring-cloud-gateway-2.0.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml index bfb4ad8979..9973fe43dc 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-spring-cloud-gateway-2.1.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml index ee9b877aaa..dae580784f 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml index c7dfeb2165..73ed729672 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml index 0741114c6b..bec5510816 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT optional-spring-cloud diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml index 1ae8f4983f..6e599a881a 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml index 4239b8e95b..dc75494925 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ optional-spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml index 93e3d73346..e4d9a96ddc 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml index deb4bb43fc..f8c0c38b0e 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml index f82260420f..e85753da89 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml index b8e7c79207..a9a8514fff 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml index ad5f4d42ec..590d2b4094 100644 --- a/apm-sniffer/optional-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml index 780020b8ea..c79b83a730 100644 --- a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-quartz-scheduler-2.x-plugin diff --git a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml index 841623347e..7a936d292d 100644 --- a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml index 3d1c99c565..6cb94a441d 100644 --- a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml index d71198b1c1..710c5df2da 100644 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml index 1e0bc3dab9..c55bf77f12 100644 --- a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml index a3b5e0e0d1..8f9166a80a 100644 --- a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT apm-zookeeper-3.4.x-plugin diff --git a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml index 53927fe911..63c5e84eec 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml @@ -20,7 +20,7 @@ optional-reporter-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml index 73d542bb39..9a752ab8e0 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml @@ -21,7 +21,7 @@ optional-reporter-plugins org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/pom.xml b/apm-sniffer/optional-reporter-plugins/pom.xml index feb2ec0daf..608e4171ee 100644 --- a/apm-sniffer/optional-reporter-plugins/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/pom.xml b/apm-sniffer/pom.xml index 25c5c2de53..8f5d3c0c32 100644 --- a/apm-sniffer/pom.xml +++ b/apm-sniffer/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT 4.0.0 diff --git a/changes/changes-9.2.0.md b/changes/changes-9.2.0.md new file mode 100644 index 0000000000..a5eecc0d2d --- /dev/null +++ b/changes/changes-9.2.0.md @@ -0,0 +1,27 @@ +Changes by Version +================== +Release Notes. + +9.2.0 +------------------ + +* Fix NoSuchMethodError in mvc-annotation-commons and change deprecated method. +* Fix forkjoinpool plugin in JDK11. +* Support for tracing spring-cloud-gateway 4.x in gateway-4.x-plugin. +* Fix re-transform bug when plugin enhanced class proxy parent method. +* Fix error HTTP status codes not recording as SLA failures in Vert.x plugins. +* Support for HttpExchange request tracing. +* Support tracing for async producing, batch sync consuming, and batch async consuming in rocketMQ-client-java-5.x-plugin. +* Convert the Redisson span into an async span. +* Rename system env name from `sw_plugin_kafka_producer_config` to `SW_PLUGIN_KAFKA_PRODUCER_CONFIG`. +* Support for ActiveMQ-Artemis messaging tracing. +* Archive the expired plugins `impala-jdbc-2.6.x-plugin`. +* Fix a bug in Spring Cloud Gateway if HttpClientFinalizer#send does not invoke, the span created at NettyRoutingFilterInterceptor can not stop. +* Fix not tracing in HttpClient v5 when HttpHost(arg[0]) is null but `RoutingSupport#determineHost` works. +* Support across thread tracing for SOFA-RPC. +* Update Jedis 4.x plugin to support Sharding and Cluster models. + +#### Documentation +* Update docs to describe `expired-plugins`. + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/204?closed=1) diff --git a/pom.xml b/pom.xml index e5b629f0e0..c6dca564f9 100755 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent - 9.2.0-SNAPSHOT + 9.3.0-SNAPSHOT org.apache From bc20c6e888e35c6a9bc9aba92c907976c3ad1187 Mon Sep 17 00:00:00 2001 From: dingjiefei <1264677051@qq.com> Date: Wed, 10 Apr 2024 22:14:14 +0800 Subject: [PATCH 003/114] remove idleCount in druid plugin (#679) --- .../druid/v1/PoolingAddDruidDataSourceInterceptor.java | 3 +-- .../scenarios/druid-1.x-scenario/config/expectedData.yaml | 8 +------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/druid/v1/PoolingAddDruidDataSourceInterceptor.java b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/druid/v1/PoolingAddDruidDataSourceInterceptor.java index 63a85409de..03416103b2 100644 --- a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/druid/v1/PoolingAddDruidDataSourceInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/druid/v1/PoolingAddDruidDataSourceInterceptor.java @@ -58,10 +58,9 @@ public void handleMethodException(Class clazz, Method method, Object[] allArgume } private Map>> getMetrics() { - Map>> metricMap = new HashMap(); + Map>> metricMap = new HashMap<>(); metricMap.put("activeCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getActiveCount()); metricMap.put("poolingCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getPoolingCount()); - metricMap.put("idleCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) (druidDataSource.getPoolingCount() - druidDataSource.getActiveCount())); metricMap.put("lockQueueLength", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getLockQueueLength()); metricMap.put("maxWaitThreadCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getMaxWaitThreadCount()); metricMap.put("commitCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getCommitCount()); diff --git a/test/plugin/scenarios/druid-1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/druid-1.x-scenario/config/expectedData.yaml index 79b64a8ab5..ca4a349b5b 100644 --- a/test/plugin/scenarios/druid-1.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/druid-1.x-scenario/config/expectedData.yaml @@ -206,7 +206,7 @@ segmentItems: - {key: http.status_code, value: '200'} meterItems: - serviceName: druid-1.x-scenario - meterSize: 14 + meterSize: 13 meters: - meterId: name: datasource @@ -220,12 +220,6 @@ meterItems: - {name: name, value: test_mysql-server:3306} - {name: status, value: poolingCount} singleValue: ge 0 - - meterId: - name: datasource - tags: - - {name: name, value: test_mysql-server:3306} - - {name: status, value: idleCount} - singleValue: ge 0 - meterId: name: datasource tags: From 23287f90c8afe913528da28a5002b95f54030631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Wed, 10 Apr 2024 23:03:16 +0800 Subject: [PATCH 004/114] Fix CHANGES.md (#680) --- CHANGES.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ce908f8278..275c823e94 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,10 +5,7 @@ Release Notes. 9.3.0 ------------------ - - -#### Documentation -* Update docs to describe `expired-plugins`. +* Remove `idleCount` tag in Alibaba Druid meter plugin. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) From ec30b5f53db297b26da4e8df89dec3c9d428ef53 Mon Sep 17 00:00:00 2001 From: ForrestWang123 <157256498+ForrestWang123@users.noreply.github.com> Date: Thu, 18 Apr 2024 21:19:50 +0800 Subject: [PATCH 005/114] Fix NPE in handleMethodException method of apm-jdk-threadpool-plugin. (#681) Co-authored-by: forrestwang --- CHANGES.md | 1 + .../apm/plugin/AbstractThreadingPoolInterceptor.java | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 275c823e94..dfe870b619 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Release Notes. ------------------ * Remove `idleCount` tag in Alibaba Druid meter plugin. +* Fix NPE in handleMethodException method of apm-jdk-threadpool-plugin. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) 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 7239453074..c72c1424b5 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 @@ -63,6 +63,10 @@ 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()) { + return; + } + ContextManager.activeSpan().log(t); } } From 1a010470076ba7f206f4fd6559d04136bea73417 Mon Sep 17 00:00:00 2001 From: ForrestWang123 <157256498+ForrestWang123@users.noreply.github.com> Date: Fri, 19 Apr 2024 08:51:09 +0800 Subject: [PATCH 006/114] Fix NPE in handleMethodException method of apm-jdk-threadpool-plugin. (#681) (#682) Co-authored-by: forrestwang --- .../AbstractThreadingPoolInterceptor.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 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 c72c1424b5..e11c260f42 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 @@ -28,22 +28,11 @@ 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]; - - // Avoid duplicate enhancement, such as the case where it has already been enhanced by RunnableWrapper or CallableWrapper with toolkit. - if (argument instanceof EnhancedInstance && ((EnhancedInstance) argument).getSkyWalkingDynamicField() instanceof ContextSnapshot) { + if (notToEnhance(allArguments)) { return; } - Object wrappedObject = wrap(argument); + Object wrappedObject = wrap(allArguments[0]); if (wrappedObject != null) { allArguments[0] = wrappedObject; } @@ -63,10 +52,25 @@ 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()) { + if (notToEnhance(allArguments)) { return; } ContextManager.activeSpan().log(t); } + + private boolean notToEnhance(Object[] allArguments) { + if (!ContextManager.isActive()) { + return true; + } + + if (allArguments == null || allArguments.length < 1) { + return true; + } + + Object argument = allArguments[0]; + + // Avoid duplicate enhancement, such as the case where it has already been enhanced by RunnableWrapper or CallableWrapper with toolkit. + return argument instanceof EnhancedInstance && ((EnhancedInstance) argument).getSkyWalkingDynamicField() instanceof ContextSnapshot; + } } From d37ee271c46221014beb8fcdd04b6aeb3badb5fa Mon Sep 17 00:00:00 2001 From: Chen Ziyan Date: Fri, 26 Apr 2024 14:01:13 +0800 Subject: [PATCH 007/114] Add support for C3P0 connection pool tracing (#683) --- .github/workflows/plugins-jdk17-test.1.yaml | 2 + CHANGES.md | 1 + .../trace/component/ComponentsDefine.java | 3 + .../apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml | 49 +++ .../apm/plugin/c3p0/PoolConstants.java | 34 +++ .../PoolingConnectionCloseInterceptor.java | 62 ++++ .../c3p0/PoolingConnectionGetInterceptor.java | 61 ++++ .../c3p0/PoolingCreationInterceptor.java | 132 ++++++++ ...C3P0NewProxyConnectionInstrumentation.java | 72 +++++ .../C3P0PoolManagerInstrumentation.java | 72 +++++ .../C3P0PooledDataSourceInstrumentation.java | 72 +++++ .../src/main/resources/skywalking-plugin.def | 19 ++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 6 + .../bin/startup.sh | 21 ++ .../config/expectedData.yaml | 288 ++++++++++++++++++ .../configuration.yml | 32 ++ .../c3p0-0.9.0.x-0.9.1.x-scenario/pom.xml | 127 ++++++++ .../src/main/assembly/assembly.xml | 41 +++ .../apm/testcase/c3p0/c3p0/Application.java | 34 +++ .../apm/testcase/c3p0/c3p0/MysqlConfig.java | 57 ++++ .../c3p0/c3p0/controller/CaseController.java | 58 ++++ .../c3p0/c3p0/service/CaseService.java | 72 +++++ .../src/main/resources/application.yaml | 23 ++ .../src/main/resources/jdbc.properties | 19 ++ .../src/main/resources/log4j2.xml | 30 ++ .../support-version.list | 18 ++ .../bin/startup.sh | 21 ++ .../config/expectedData.yaml | 288 ++++++++++++++++++ .../configuration.yml | 32 ++ .../c3p0-0.9.2.x-0.10.x-scenario/pom.xml | 127 ++++++++ .../src/main/assembly/assembly.xml | 41 +++ .../testcase/c3p0/mchange/Application.java | 34 +++ .../testcase/c3p0/mchange/MysqlConfig.java | 57 ++++ .../mchange/controller/CaseController.java | 58 ++++ .../c3p0/mchange/service/CaseService.java | 73 +++++ .../src/main/resources/application.yaml | 23 ++ .../src/main/resources/jdbc.properties | 19 ++ .../src/main/resources/log4j2.xml | 30 ++ .../support-version.list | 19 ++ 41 files changed, 2229 insertions(+) create mode 100644 apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolConstants.java create mode 100644 apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingConnectionCloseInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingConnectionGetInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingCreationInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0NewProxyConnectionInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0PoolManagerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0PooledDataSourceInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/resources/skywalking-plugin.def create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/bin/startup.sh create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/config/expectedData.yaml create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/configuration.yml create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/pom.xml create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/assembly/assembly.xml create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/Application.java create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/MysqlConfig.java create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/controller/CaseController.java create mode 100644 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/service/CaseService.java create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/application.yaml create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/jdbc.properties create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/log4j2.xml create mode 100755 test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/support-version.list create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/bin/startup.sh create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/config/expectedData.yaml create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/configuration.yml create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/pom.xml create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/assembly/assembly.xml create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/Application.java create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/MysqlConfig.java create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/controller/CaseController.java create mode 100644 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/service/CaseService.java create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/application.yaml create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/jdbc.properties create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/log4j2.xml create mode 100755 test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index d469d4c2ef..61bb8fa75a 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -60,6 +60,8 @@ jobs: - gateway-4.x-scenario - httpexchange-scenario - activemq-artemis-2.x-scenario + - c3p0-0.9.0.x-0.9.1.x-scenario + - c3p0-0.9.2.x-0.10.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index dfe870b619..790ba4c6dc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ Release Notes. * Remove `idleCount` tag in Alibaba Druid meter plugin. * Fix NPE in handleMethodException method of apm-jdk-threadpool-plugin. +* Support for C3P0 connection pool tracing. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index 2334cb58e0..5364ff0eda 100755 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -244,4 +244,7 @@ public class ComponentsDefine { public static final OfficialComponent NACOS = new OfficialComponent(150, "Nacos"); public static final OfficialComponent NETTY_HTTP = new OfficialComponent(151, "Netty-http"); + + public static final OfficialComponent C3P0 = new OfficialComponent(152, "c3p0"); + } diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml new file mode 100644 index 0000000000..3d61e4cc0d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml @@ -0,0 +1,49 @@ + + + + + + apm-sdk-plugin + org.apache.skywalking + 9.3.0-SNAPSHOT + + 4.0.0 + + apm-c3p0-0.9.x-plugin + jar + c3p0-0.9.x-plugin + + + 0.9.5 + + + + + com.mchange + c3p0 + ${c3p0.version} + provided + + + org.apache.skywalking + apm-jdbc-commons + ${project.version} + provided + + + diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolConstants.java b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolConstants.java new file mode 100644 index 0000000000..4536cd5112 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolConstants.java @@ -0,0 +1,34 @@ +/* + * 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.c3p0; + +public class PoolConstants { + public static final String POOL_CONNECTION = "C3P0/Connection/"; + public static final String METER_NAME = "datasource"; + public static final String METER_TAG_NAME = "name"; + public static final String METER_TAG_STATUS = "status"; + + //==================== METRICS ========================// + public static final String NUM_TOTAL_CONNECTIONS = "numTotalConnections"; + public static final String NUM_BUSY_CONNECTIONS = "numBusyConnections"; + public static final String NUM_IDLE_CONNECTIONS = "numIdleConnections"; + public static final String MAX_IDLE_TIME = "maxIdleTime"; + public static final String MIN_POOL_SIZE = "minPoolSize"; + public static final String MAX_POOL_SIZE = "maxPoolSize"; + public static final String INITIAL_POOL_SIZE = "initialPoolSize"; +} diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingConnectionCloseInterceptor.java b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingConnectionCloseInterceptor.java new file mode 100644 index 0000000000..aa3a41fa33 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingConnectionCloseInterceptor.java @@ -0,0 +1,62 @@ +/* + * 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.c3p0; + +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 org.apache.skywalking.apm.network.trace.component.ComponentsDefine; + +import java.lang.reflect.Method; + +/** + * {@link PoolingConnectionCloseInterceptor} intercepted the method of C3P0 closing connection. + */ +public class PoolingConnectionCloseInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, + Method method, + Object[] allArguments, + Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + AbstractSpan span = ContextManager.createLocalSpan(PoolConstants.POOL_CONNECTION + method.getName()); + span.setComponent(ComponentsDefine.C3P0); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, + Method method, + Object[] allArguments, + Class[] argumentsTypes, + Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, + Method method, + Object[] allArguments, + Class[] argumentsTypes, + Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingConnectionGetInterceptor.java b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingConnectionGetInterceptor.java new file mode 100644 index 0000000000..aff1e69e6c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingConnectionGetInterceptor.java @@ -0,0 +1,61 @@ +/* + * 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.c3p0; + +import java.lang.reflect.Method; +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 org.apache.skywalking.apm.network.trace.component.ComponentsDefine; + +/** + * {@link PoolingConnectionGetInterceptor} intercepted the method of C3P0 getting connection. + */ +public class PoolingConnectionGetInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, + Method method, + Object[] allArguments, + Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + AbstractSpan span = ContextManager.createLocalSpan(PoolConstants.POOL_CONNECTION + method.getName()); + span.setComponent(ComponentsDefine.C3P0); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, + Method method, + Object[] allArguments, + Class[] argumentsTypes, + Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, + Method method, + Object[] allArguments, + Class[] argumentsTypes, + Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingCreationInterceptor.java b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingCreationInterceptor.java new file mode 100644 index 0000000000..6a5514e8c5 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/PoolingCreationInterceptor.java @@ -0,0 +1,132 @@ +/* + * 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.c3p0; + +import com.mchange.v2.c3p0.C3P0Registry; +import com.mchange.v2.c3p0.ComboPooledDataSource; +import java.lang.reflect.Method; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.meter.MeterFactory; +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.plugin.jdbc.connectionurl.parser.URLParser; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +/** + * {@link PoolingCreationInterceptor} intercepted the method of pool creation. + */ +public class PoolingCreationInterceptor implements InstanceMethodsAroundInterceptor { + private static final Set TOKEN_MAP = new HashSet<>(16); + + @Override + public void beforeMethod(final EnhancedInstance enhancedInstance, + final Method method, + final Object[] objects, + final Class[] classes, + final MethodInterceptResult methodInterceptResult) throws Throwable { + + } + + @Override + public Object afterMethod(final EnhancedInstance enhancedInstance, + final Method method, + final Object[] objects, + final Class[] classes, + final Object ret) throws Throwable { + C3P0Registry.getPooledDataSources().forEach(obj -> { + ComboPooledDataSource pooledDataSource = (ComboPooledDataSource) obj; + if (!TOKEN_MAP.contains(pooledDataSource.getIdentityToken())) { + ConnectionInfo connectionInfo = URLParser.parser(pooledDataSource.getJdbcUrl()); + String tagValue = connectionInfo.getDatabaseName() + "_" + connectionInfo.getDatabasePeer(); + Map>> metricMap = getMetrics(); + metricMap.forEach( + (key, value) -> MeterFactory.gauge(PoolConstants.METER_NAME, value.apply(pooledDataSource)) + .tag(PoolConstants.METER_TAG_NAME, tagValue) + .tag(PoolConstants.METER_TAG_STATUS, key) + .build()); + TOKEN_MAP.add(pooledDataSource.getIdentityToken()); + } + }); + return ret; + } + + @Override + public void handleMethodException(final EnhancedInstance enhancedInstance, + final Method method, + final Object[] objects, + final Class[] classes, + final Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } + + private Map>> getMetrics() { + Map>> metricMap = new HashMap<>(); + metricMap.put(PoolConstants.NUM_TOTAL_CONNECTIONS, (ComboPooledDataSource pooledDataSource) -> () -> { + double numConnections = 0; + try { + numConnections = pooledDataSource.getNumConnections(); + } catch (SQLException e) { + ContextManager.activeSpan().errorOccurred().log(e); + } + return numConnections; + }); + metricMap.put(PoolConstants.NUM_BUSY_CONNECTIONS, (ComboPooledDataSource pooledDataSource) -> () -> { + double numBusyConnections = 0; + try { + numBusyConnections = pooledDataSource.getNumBusyConnections(); + } catch (SQLException e) { + ContextManager.activeSpan().errorOccurred().log(e); + } + return numBusyConnections; + }); + metricMap.put(PoolConstants.NUM_IDLE_CONNECTIONS, (ComboPooledDataSource pooledDataSource) -> () -> { + double numIdleConnections = 0; + try { + numIdleConnections = pooledDataSource.getNumIdleConnections(); + } catch (SQLException e) { + ContextManager.activeSpan().errorOccurred().log(e); + } + return numIdleConnections; + }); + metricMap.put( + PoolConstants.MAX_IDLE_TIME, + (ComboPooledDataSource pooledDataSource) -> () -> (double) pooledDataSource.getMaxIdleTime() + ); + metricMap.put( + PoolConstants.MIN_POOL_SIZE, + (ComboPooledDataSource pooledDataSource) -> () -> (double) pooledDataSource.getMinPoolSize() + ); + metricMap.put( + PoolConstants.MAX_POOL_SIZE, + (ComboPooledDataSource pooledDataSource) -> () -> (double) pooledDataSource.getMaxPoolSize() + ); + metricMap.put( + PoolConstants.INITIAL_POOL_SIZE, + (ComboPooledDataSource pooledDataSource) -> () -> (double) pooledDataSource.getInitialPoolSize() + ); + return metricMap; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0NewProxyConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0NewProxyConnectionInstrumentation.java new file mode 100644 index 0000000000..e049023a23 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0NewProxyConnectionInstrumentation.java @@ -0,0 +1,72 @@ +/* + * 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.c3p0.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 org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * C3p0 is a mature, highly concurrent JDBC Connection pooling library, with support for caching and reuse of + * PreparedStatement objects. Defined by the jdbc3 spec and the optional extensions to jdbc2. c3p0 now also fully + * supports the jdbc4. {@link C3P0NewProxyConnectionInstrumentation} defines the instance methods enhance plugin for + * connection closed + */ +public class C3P0NewProxyConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "com.mchange.v2.c3p0.impl.NewProxyConnection"; + private static final String ENHANCE_METHOD = "close"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.c3p0.PoolingConnectionCloseInterceptor"; + + @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 getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0PoolManagerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0PoolManagerInstrumentation.java new file mode 100644 index 0000000000..57510c2362 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0PoolManagerInstrumentation.java @@ -0,0 +1,72 @@ +/* + * 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.c3p0.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 org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * C3p0 is a mature, highly concurrent JDBC Connection pooling library, with support for caching and reuse of + * PreparedStatement objects. Defined by the jdbc3 spec and the optional extensions to jdbc2. c3p0 now also fully + * supports the jdbc4. { @link C3P0PoolManagerInstrumentation} defines the instance methods enhance plugin for pool + * creation. + */ +public class C3P0PoolManagerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "com.mchange.v2.c3p0.impl.C3P0PooledConnectionPoolManager"; + private static final String ENHANCE_METHOD = "createPooledConnectionPool"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.c3p0.PoolingCreationInterceptor"; + + @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 getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0PooledDataSourceInstrumentation.java b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0PooledDataSourceInstrumentation.java new file mode 100644 index 0000000000..e2ae84731b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/c3p0/define/C3P0PooledDataSourceInstrumentation.java @@ -0,0 +1,72 @@ +/* + * 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.c3p0.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 org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * C3p0 is a mature, highly concurrent JDBC Connection pooling library, with support for caching and reuse of + * PreparedStatement objects. Defined by the jdbc3 spec and the optional extensions to jdbc2. c3p0 now also fully + * supports the jdbc4. { @link C3P0PooledDataSourceInstrumentation} defines the instance methods enhance plugin for + * connection init + */ +public class C3P0PooledDataSourceInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "com.mchange.v2.c3p0.ComboPooledDataSource"; + private static final String ENHANCE_METHOD = "getConnection"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.c3p0.PoolingConnectionGetInterceptor"; + + @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 getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..bbb99e5908 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/src/main/resources/skywalking-plugin.def @@ -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. + +c3p0-0.9.x=org.apache.skywalking.apm.plugin.c3p0.define.C3P0NewProxyConnectionInstrumentation +c3p0-0.9.x=org.apache.skywalking.apm.plugin.c3p0.define.C3P0PoolManagerInstrumentation +c3p0-0.9.x=org.apache.skywalking.apm.plugin.c3p0.define.C3P0PooledDataSourceInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index bf07afa7a6..bce4312dfc 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -136,6 +136,7 @@ aerospike-plugin rocketMQ-client-java-5.x-plugin activemq-artemis-jakarta-client-2.x-plugin + c3p0-0.9.x-plugin pom 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 16136fce70..d8c4d160bb 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -176,3 +176,4 @@ - spring-webflux-6.x - spring-webflux-6.x-webclient - activemq-artemis-jakarta-client-2.x +- c3p0-0.9.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index da1aef6411..a51d267460 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -148,6 +148,7 @@ metrics based on the tracing data. * [Apache Commons DBCP](https://github.com/apache/commons-dbcp) 2.x * [Alibaba Druid](https://github.com/alibaba/druid) 1.x * [HikariCP](https://github.com/brettwooldridge/HikariCP) 3.x -> 4.x + * [C3P0](https://github.com/swaldman/c3p0) 0.9.0 -> 0.10.0 * Logging Framework * [log4j](https://github.com/apache/log4j) 2.x * [log4j2](https://github.com/apache/logging-log4j2) 1.2.x @@ -166,6 +167,11 @@ The meter plugin provides the advanced metrics collections, which are not a part * [Dubbo](https://github.com/apache/dubbo) 2.5.x -> 2.7.x * [Jetty](https://github.com/eclipse/jetty.project) 9.1.x -> 11.x * [Grizzly](https://github.com/eclipse-ee4j/grizzly) 2.3.x -> 4.x +* Connection Pool + * [Apache Commons DBCP](https://github.com/apache/commons-dbcp) 2.x + * [Alibaba Druid](https://github.com/alibaba/druid) 1.x + * [HikariCP](https://github.com/brettwooldridge/HikariCP) 3.x -> 4.x + * [C3P0](https://github.com/swaldman/c3p0) 0.9.0 -> 0.10.0 ___ ¹Due to license incompatibilities/restrictions these plugins are hosted and released in 3rd part repository, go to [SkyAPM java plugin extension repository](https://github.com/SkyAPM/java-plugin-extensions) to get these. diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/bin/startup.sh b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/bin/startup.sh new file mode 100755 index 0000000000..ec6c3c19a5 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-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/c3p0-0.9.0.x-0.9.1.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/config/expectedData.yaml new file mode 100755 index 0000000000..545afa54ef --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/config/expectedData.yaml @@ -0,0 +1,288 @@ +# 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: c3p0-0.9.0.x-0.9.1.x-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 1 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 2 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: "CREATE TABLE test_C3P0(\nid VARCHAR(1) PRIMARY KEY, \nvalue VARCHAR(1)\ + \ NOT NULL)" + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 3 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 4 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 5 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: 'INSERT INTO test_C3P0(id, value) VALUES(1,1)' + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 6 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 7 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 8 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: 'SELECT id, value FROM test_C3P0 WHERE id=1' + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 9 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 10 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 11 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: "DELETE FROM test_C3P0 WHERE id=1" + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 12 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 13 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 14 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: "DROP table test_C3P0" + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 15 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: GET:/c3p0-0.9.0.x-0.9.1.x-scenario/case/c3p0-0.9.0.x-0.9.1.x-scenario + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/c3p0-0.9.0.x-0.9.1.x-scenario/case/c3p0-0.9.0.x-0.9.1.x-scenario'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} +meterItems: +- serviceName: c3p0-0.9.0.x-0.9.1.x-scenario + meterSize: 12 + meters: + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: initialPoolSize} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: maxIdleTime} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: maxPoolSize} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: minPoolSize} + singleValue: ge -1 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: numBusyConnections} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: numIdleConnections} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: numTotalConnections} + singleValue: ge 0 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: core_pool_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 1 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: max_pool_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 1 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: pool_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 0 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: active_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 0 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: queue_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 0 diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/configuration.yml b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/configuration.yml new file mode 100755 index 0000000000..d05855afe4 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/configuration.yml @@ -0,0 +1,32 @@ +# 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/c3p0-0.9.0.x-0.9.1.x-scenario/case/c3p0-0.9.0.x-0.9.1.x-scenario +healthCheck: http://localhost:8080/c3p0-0.9.0.x-0.9.1.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: +depends_on: + - mysql-server +dependencies: + mysql-server: + image: mysql:5.7 + hostname: mysql-server + expose: + - "3306" + environment: + - MYSQL_ROOT_PASSWORD=root + - MYSQL_DATABASE=test diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/pom.xml b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/pom.xml new file mode 100755 index 0000000000..0a3408ade0 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/pom.xml @@ -0,0 +1,127 @@ + + + + + org.apache.skywalking.apm.testcase + c3p0-0.9.0.x-0.9.1.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + 0.9.1.2 + ${test.framework.version} + 2.1.6.RELEASE + + + skywalking-c3p0-0.9.0.x-0.9.1.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + mysql + mysql-connector-java + 5.1.25 + + + + c3p0 + c3p0 + ${test.framework.version} + + + + + c3p0-0.9.0.x-0.9.1.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${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/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/assembly/assembly.xml new file mode 100755 index 0000000000..6e2d37867c --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/c3p0-0.9.0.x-0.9.1.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/Application.java b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/Application.java new file mode 100755 index 0000000000..2accc46e0f --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/Application.java @@ -0,0 +1,34 @@ +/* + * 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.testcase.c3p0.c3p0; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } +} diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/MysqlConfig.java b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/MysqlConfig.java new file mode 100755 index 0000000000..bdc0102b61 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/MysqlConfig.java @@ -0,0 +1,57 @@ +/* + * 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.testcase.c3p0.c3p0; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class MysqlConfig { + private static Logger LOGGER = LogManager.getLogger(MysqlConfig.class); + private static String URL; + private static String USER_NAME; + private static String PASSWORD; + + static { + InputStream inputStream = MysqlConfig.class.getClassLoader().getResourceAsStream("jdbc.properties"); + Properties properties = new Properties(); + try { + properties.load(inputStream); + } catch (IOException e) { + LOGGER.error("Failed to load config", e); + } + URL = properties.getProperty("mysql.url"); + USER_NAME = properties.getProperty("mysql.username"); + PASSWORD = properties.getProperty("mysql.password"); + } + + public static String getUrl() { + return URL; + } + + public static String getUserName() { + return USER_NAME; + } + + public static String getPassword() { + return PASSWORD; + } +} diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/controller/CaseController.java b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/controller/CaseController.java new file mode 100755 index 0000000000..447f843413 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/controller/CaseController.java @@ -0,0 +1,58 @@ +/* + * 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.testcase.c3p0.c3p0.controller; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.c3p0.c3p0.service.CaseService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +public class CaseController { + + @Autowired + CaseService caseService; + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + private static final String SUCCESS = "Success"; + + @RequestMapping("/c3p0-0.9.0.x-0.9.1.x-scenario") + @ResponseBody + public String testcase() throws Exception { + try { + caseService.testCase(); + } catch (Exception e) { + LOGGER.error("Failed to execute sql.", e); + throw e; + } + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() throws Exception { + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/service/CaseService.java b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/service/CaseService.java new file mode 100644 index 0000000000..ee2c38ed21 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/c3p0/service/CaseService.java @@ -0,0 +1,72 @@ +/* + * 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.testcase.c3p0.c3p0.service; + +import com.mchange.v2.c3p0.ComboPooledDataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import org.apache.skywalking.apm.testcase.c3p0.c3p0.MysqlConfig; +import org.springframework.stereotype.Service; + +@Service +public class CaseService { + + public static ComboPooledDataSource DS; + private static final String CREATE_TABLE_SQL = "CREATE TABLE test_C3P0(\n" + "id VARCHAR(1) PRIMARY KEY, \n" + "value VARCHAR(1) NOT NULL)"; + private static final String INSERT_DATA_SQL = "INSERT INTO test_C3P0(id, value) VALUES(1,1)"; + private static final String QUERY_DATA_SQL = "SELECT id, value FROM test_C3P0 WHERE id=1"; + private static final String DELETE_DATA_SQL = "DELETE FROM test_C3P0 WHERE id=1"; + private static final String DROP_TABLE_SQL = "DROP table test_C3P0"; + + static { + try { + DS = new ComboPooledDataSource(); + DS.setDriverClass("com.mysql.jdbc.Driver"); + DS.setJdbcUrl(MysqlConfig.getUrl()); + DS.setUser(MysqlConfig.getUserName()); + DS.setPassword(MysqlConfig.getPassword()); + DS.setAcquireIncrement(1); + DS.setInitialPoolSize(5); + DS.setMinPoolSize(1); + DS.setMaxIdleTime(10); + DS.setTestConnectionOnCheckin(false); + DS.setTestConnectionOnCheckout(false); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void testCase() { + sqlExecutor(DS, CREATE_TABLE_SQL); + sqlExecutor(DS, INSERT_DATA_SQL); + sqlExecutor(DS, QUERY_DATA_SQL); + sqlExecutor(DS, DELETE_DATA_SQL); + sqlExecutor(DS, DROP_TABLE_SQL); + } + + public void sqlExecutor(ComboPooledDataSource dataSource, String sql) { + try (Connection conn = dataSource.getConnection();) { + Statement statement = conn.createStatement(); + statement.execute(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/application.yaml new file mode 100755 index 0000000000..66a7a51fd1 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +# +# 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 + servlet: + context-path: /c3p0-0.9.0.x-0.9.1.x-scenario +logging: + config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/jdbc.properties b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/jdbc.properties new file mode 100755 index 0000000000..8051777cce --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/jdbc.properties @@ -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. +# +mysql.url=jdbc:mysql://mysql-server:3306/test?serverTimezone=CST&useLocalSessionState=true +mysql.username=root +mysql.password=root \ No newline at end of file diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/log4j2.xml new file mode 100755 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/support-version.list b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/support-version.list new file mode 100755 index 0000000000..730308cbca --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/support-version.list @@ -0,0 +1,18 @@ +# 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. + +0.9.0.4 +0.9.1.2 \ No newline at end of file diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/bin/startup.sh b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/bin/startup.sh new file mode 100755 index 0000000000..9ee496ba82 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-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/c3p0-0.9.2.x-0.10.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/config/expectedData.yaml new file mode 100755 index 0000000000..68f931fa29 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/config/expectedData.yaml @@ -0,0 +1,288 @@ +# 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: c3p0-0.9.2.x-0.10.x-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 1 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 2 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: "CREATE TABLE test_C3P0(\nid VARCHAR(1) PRIMARY KEY, \nvalue VARCHAR(1)\ + \ NOT NULL)" + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 3 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 4 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 5 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: 'INSERT INTO test_C3P0(id, value) VALUES(1,1)' + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 6 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 7 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 8 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: 'SELECT id, value FROM test_C3P0 WHERE id=1' + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 9 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 10 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 11 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: "DELETE FROM test_C3P0 WHERE id=1" + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 12 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: C3P0/Connection/getConnection + parentSpanId: 0 + spanId: 13 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 14 + startTime: gt 0 + endTime: gt 0 + componentId: 33 + isError: false + spanType: Exit + peer: mysql-server:3306 + skipAnalysis: false + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: "DROP table test_C3P0" + - operationName: C3P0/Connection/close + parentSpanId: 0 + spanId: 15 + startTime: gt 0 + endTime: gt 0 + componentId: 152 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + - operationName: GET:/c3p0-0.9.2.x-0.10.x-scenario/case/c3p0-0.9.2.x-0.10.x-scenario + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/c3p0-0.9.2.x-0.10.x-scenario/case/c3p0-0.9.2.x-0.10.x-scenario'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} +meterItems: +- serviceName: c3p0-0.9.2.x-0.10.x-scenario + meterSize: 12 + meters: + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: initialPoolSize} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: maxIdleTime} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: maxPoolSize} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: minPoolSize} + singleValue: ge -1 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: numBusyConnections} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: numIdleConnections} + singleValue: ge 0 + - meterId: + name: datasource + tags: + - {name: name, value: test_mysql-server:3306} + - {name: status, value: numTotalConnections} + singleValue: ge 0 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: core_pool_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 1 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: max_pool_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 1 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: pool_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 0 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: active_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 0 + - meterId: + name: thread_pool + tags: + - {name: metric_type, value: queue_size} + - {name: pool_name, value: tomcat_execute_pool} + singleValue: ge 0 diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/configuration.yml b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/configuration.yml new file mode 100755 index 0000000000..1fb61085e6 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/configuration.yml @@ -0,0 +1,32 @@ +# 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/c3p0-0.9.2.x-0.10.x-scenario/case/c3p0-0.9.2.x-0.10.x-scenario +healthCheck: http://localhost:8080/c3p0-0.9.2.x-0.10.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: +depends_on: + - mysql-server +dependencies: + mysql-server: + image: mysql:5.7 + hostname: mysql-server + expose: + - "3306" + environment: + - MYSQL_ROOT_PASSWORD=root + - MYSQL_DATABASE=test diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/pom.xml b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/pom.xml new file mode 100755 index 0000000000..dc4e7cf830 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/pom.xml @@ -0,0 +1,127 @@ + + + + + org.apache.skywalking.apm.testcase + c3p0-0.9.2.x-0.10.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + 0.9.5.5 + ${test.framework.version} + 2.1.6.RELEASE + + + skywalking-c3p0-0.9.2.x-0.10.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + mysql + mysql-connector-java + 5.1.25 + + + + com.mchange + c3p0 + ${test.framework.version} + + + + + c3p0-0.9.2.x-0.10.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${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/c3p0-0.9.2.x-0.10.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/assembly/assembly.xml new file mode 100755 index 0000000000..724b0f4a36 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/c3p0-0.9.2.x-0.10.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/Application.java b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/Application.java new file mode 100755 index 0000000000..6f88c48cbc --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/Application.java @@ -0,0 +1,34 @@ +/* + * 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.testcase.c3p0.mchange; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } +} diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/MysqlConfig.java b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/MysqlConfig.java new file mode 100755 index 0000000000..8762486f35 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/MysqlConfig.java @@ -0,0 +1,57 @@ +/* + * 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.testcase.c3p0.mchange; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class MysqlConfig { + private static Logger LOGGER = LogManager.getLogger(MysqlConfig.class); + private static String URL; + private static String USER_NAME; + private static String PASSWORD; + + static { + InputStream inputStream = MysqlConfig.class.getClassLoader().getResourceAsStream("jdbc.properties"); + Properties properties = new Properties(); + try { + properties.load(inputStream); + } catch (IOException e) { + LOGGER.error("Failed to load config", e); + } + URL = properties.getProperty("mysql.url"); + USER_NAME = properties.getProperty("mysql.username"); + PASSWORD = properties.getProperty("mysql.password"); + } + + public static String getUrl() { + return URL; + } + + public static String getUserName() { + return USER_NAME; + } + + public static String getPassword() { + return PASSWORD; + } +} diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/controller/CaseController.java b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/controller/CaseController.java new file mode 100755 index 0000000000..c9d8432531 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/controller/CaseController.java @@ -0,0 +1,58 @@ +/* + * 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.testcase.c3p0.mchange.controller; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.c3p0.mchange.service.CaseService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +public class CaseController { + + @Autowired + CaseService caseService; + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + private static final String SUCCESS = "Success"; + + @RequestMapping("/c3p0-0.9.2.x-0.10.x-scenario") + @ResponseBody + public String testcase() throws Exception { + try { + caseService.testCase(); + } catch (Exception e) { + LOGGER.error("Failed to execute sql.", e); + throw e; + } + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() throws Exception { + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/service/CaseService.java b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/service/CaseService.java new file mode 100644 index 0000000000..3d493b2a27 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/c3p0/mchange/service/CaseService.java @@ -0,0 +1,73 @@ +/* + * 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.testcase.c3p0.mchange.service; + +import com.mchange.v2.c3p0.ComboPooledDataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import org.apache.skywalking.apm.testcase.c3p0.mchange.MysqlConfig; +import org.springframework.stereotype.Service; + +@Service +public class CaseService { + + public static ComboPooledDataSource DS; + private static final String CREATE_TABLE_SQL = "CREATE TABLE test_C3P0(\n" + "id VARCHAR(1) PRIMARY KEY, \n" + "value VARCHAR(1) NOT NULL)"; + private static final String INSERT_DATA_SQL = "INSERT INTO test_C3P0(id, value) VALUES(1,1)"; + private static final String QUERY_DATA_SQL = "SELECT id, value FROM test_C3P0 WHERE id=1"; + private static final String DELETE_DATA_SQL = "DELETE FROM test_C3P0 WHERE id=1"; + private static final String DROP_TABLE_SQL = "DROP table test_C3P0"; + + static { + try { + DS = new ComboPooledDataSource(); + DS.setDriverClass("com.mysql.jdbc.Driver"); + DS.setJdbcUrl(MysqlConfig.getUrl()); + DS.setUser(MysqlConfig.getUserName()); + DS.setPassword(MysqlConfig.getPassword()); + DS.setAcquireIncrement(1); + DS.setInitialPoolSize(5); + DS.setMinPoolSize(1); + DS.setMaxIdleTime(10); + DS.setTestConnectionOnCheckin(false); + DS.setTestConnectionOnCheckout(false); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void testCase() { + sqlExecutor(DS, CREATE_TABLE_SQL); + sqlExecutor(DS, INSERT_DATA_SQL); + sqlExecutor(DS, QUERY_DATA_SQL); + sqlExecutor(DS, DELETE_DATA_SQL); + sqlExecutor(DS, DROP_TABLE_SQL); + } + + public void sqlExecutor(ComboPooledDataSource dataSource, String sql) { + try (Connection conn = dataSource.getConnection();) { + Statement statement = conn.createStatement(); + statement.execute(sql); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/application.yaml new file mode 100755 index 0000000000..88dfae1b32 --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +# +# 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 + servlet: + context-path: /c3p0-0.9.2.x-0.10.x-scenario +logging: + config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/jdbc.properties b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/jdbc.properties new file mode 100755 index 0000000000..8051777cce --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/jdbc.properties @@ -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. +# +mysql.url=jdbc:mysql://mysql-server:3306/test?serverTimezone=CST&useLocalSessionState=true +mysql.username=root +mysql.password=root \ No newline at end of file diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/log4j2.xml new file mode 100755 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/support-version.list b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/support-version.list new file mode 100755 index 0000000000..9405ba41cc --- /dev/null +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/support-version.list @@ -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. + +0.10.0 +0.9.5.5 +0.9.2.1 \ No newline at end of file From ec2a2d4188b78562ed41c9fb1115d86f5dfdc847 Mon Sep 17 00:00:00 2001 From: githubcheng2978 Date: Fri, 26 Apr 2024 22:09:36 +0800 Subject: [PATCH 008/114] Use a daemon thread to flush logs. (#684) --- CHANGES.md | 1 + .../skywalking/apm/agent/core/logging/core/FileWriter.java | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 790ba4c6dc..ba2cd6cb70 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ Release Notes. * Remove `idleCount` tag in Alibaba Druid meter plugin. * Fix NPE in handleMethodException method of apm-jdk-threadpool-plugin. * Support for C3P0 connection pool tracing. +* Use a daemon thread to flush logs. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriter.java index 4020b7a98a..adc7194e45 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriter.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/FileWriter.java @@ -97,6 +97,7 @@ public void run() { public void handle(Throwable t) { } }), "SkywalkingAgent-LogFileWriter"); + logFlusherThread.setDaemon(true); logFlusherThread.start(); } From 75deff1923715ab3ff6d62867275a23aee62db0b Mon Sep 17 00:00:00 2001 From: jiangyuan <469391363@qq.com> Date: Tue, 30 Apr 2024 23:57:47 +0800 Subject: [PATCH 009/114] Fix a wrong folder name about optional reporter (#685) --- docs/en/setup/service-agent/java-agent/advanced-reporters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/setup/service-agent/java-agent/advanced-reporters.md b/docs/en/setup/service-agent/java-agent/advanced-reporters.md index 44264d4e9f..7ecede0190 100644 --- a/docs/en/setup/service-agent/java-agent/advanced-reporters.md +++ b/docs/en/setup/service-agent/java-agent/advanced-reporters.md @@ -1,5 +1,5 @@ # Advanced Reporters -The advanced report provides an alternative way to submit the agent collected data to the backend. All of them are in the `optional-reporter-plugins` folder, move the one you needed into the `reporter-plugins` folder for the activation. **Notice, don't try to activate multiple reporters, that could cause unexpected fatal errors.** +The advanced report provides an alternative way to submit the agent collected data to the backend. All of them are in the `optional-reporter-plugins` folder, move the one you needed into the `plugins` folder for the activation. **Notice, don't try to activate multiple reporters, that could cause unexpected fatal errors.** ## Kafka Reporter The Kafka reporter plugin support report traces, JVM metrics, Instance Properties, and profiled snapshots to Kafka cluster, which is disabled in default. Move the jar of the plugin, `kafka-reporter-plugin-x.y.z.jar`, from `agent/optional-reporter-plugins` to `agent/plugins` for activating. From 1e5463c3cc3c99bbe4b89b0f5ca847c8641d2347 Mon Sep 17 00:00:00 2001 From: Chen Ziyan Date: Mon, 6 May 2024 23:49:40 +0800 Subject: [PATCH 010/114] Fix typos in URLParser. (#686) --- CHANGES.md | 1 + .../plugin/jdbc/connectionurl/parser/URLParser.java | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ba2cd6cb70..fcde635794 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Release Notes. * Fix NPE in handleMethodException method of apm-jdk-threadpool-plugin. * Support for C3P0 connection pool tracing. * Use a daemon thread to flush logs. +* Fix typos in `URLParser`. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java index ddf2f20fc7..eab319fd7e 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java @@ -33,9 +33,9 @@ public class URLParser { private static final String MARIADB_JDBC_URL_PREFIX = "jdbc:mariadb"; private static final String MSSQL_JTDS_URL_PREFIX = "jdbc:jtds:sqlserver:"; private static final String MSSQL_JDBC_URL_PREFIX = "jdbc:sqlserver:"; - private static final String KYLIN_JDBC_URK_PREFIX = "jdbc:kylin"; - private static final String IMPALA_JDBC_URK_PREFIX = "jdbc:impala"; - private static final String CLICKHOUSE_JDBC_URK_PREFIX = "jdbc:clickhouse"; + private static final String KYLIN_JDBC_URL_PREFIX = "jdbc:kylin"; + private static final String IMPALA_JDBC_URL_PREFIX = "jdbc:impala"; + private static final String CLICKHOUSE_JDBC_URL_PREFIX = "jdbc:clickhouse"; public static ConnectionInfo parser(String url) { ConnectionURLParser parser = null; @@ -54,11 +54,11 @@ public static ConnectionInfo parser(String url) { parser = new MssqlJtdsURLParser(url); } else if (lowerCaseUrl.startsWith(MSSQL_JDBC_URL_PREFIX)) { parser = new MssqlJdbcURLParser(url); - } else if (lowerCaseUrl.startsWith(KYLIN_JDBC_URK_PREFIX)) { + } else if (lowerCaseUrl.startsWith(KYLIN_JDBC_URL_PREFIX)) { parser = new KylinJdbcURLParser(url); - } else if (lowerCaseUrl.startsWith(IMPALA_JDBC_URK_PREFIX)) { + } else if (lowerCaseUrl.startsWith(IMPALA_JDBC_URL_PREFIX)) { parser = new ImpalaJdbcURLParser(url); - } else if (lowerCaseUrl.startsWith(CLICKHOUSE_JDBC_URK_PREFIX)) { + } else if (lowerCaseUrl.startsWith(CLICKHOUSE_JDBC_URL_PREFIX)) { parser = new ClickHouseURLParser(url); } return parser.parse(); From 7dd7914765c06f64733ccfd214645f70bad8a583 Mon Sep 17 00:00:00 2001 From: Chen Ziyan Date: Sat, 11 May 2024 21:33:40 +0800 Subject: [PATCH 011/114] Add pool metrics support for Derby/Sybase/SQLite/DB2/OceanBase jdbc URL format in URLParser (#687) --- CHANGES.md | 1 + .../trace/component/ComponentsDefine.java | 11 + .../connectionurl/parser/Db2URLParser.java | 129 ++++++++++++ .../connectionurl/parser/DerbyURLParser.java | 197 ++++++++++++++++++ .../parser/OceanBaseURLParser.java | 27 +++ .../connectionurl/parser/SqliteURLParser.java | 57 +++++ .../connectionurl/parser/SybaseURLParser.java | 114 ++++++++++ .../jdbc/connectionurl/parser/URLParser.java | 15 ++ .../connectionurl/parser/URLParserTest.java | 137 +++++++++++- .../java-agent/Supported-list.md | 25 ++- 10 files changed, 708 insertions(+), 5 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/Db2URLParser.java create mode 100644 apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/DerbyURLParser.java create mode 100644 apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/OceanBaseURLParser.java create mode 100644 apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/SqliteURLParser.java create mode 100644 apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/SybaseURLParser.java diff --git a/CHANGES.md b/CHANGES.md index fcde635794..6b6c759ae5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Release Notes. * Support for C3P0 connection pool tracing. * Use a daemon thread to flush logs. * Fix typos in `URLParser`. +* Add support for `Derby`/`Sybase`/`SQLite`/`DB2`/`OceanBase` jdbc url format in `URLParser`. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index 5364ff0eda..b7307ebac7 100755 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -247,4 +247,15 @@ public class ComponentsDefine { public static final OfficialComponent C3P0 = new OfficialComponent(152, "c3p0"); + public static final OfficialComponent DERBY_JDBC_DRIVER = new OfficialComponent(153, "Derby-jdbc-driver"); + + public static final OfficialComponent SQLITE_JDBC_DRIVER = new OfficialComponent(154, "Sqlite-jdbc-driver"); + + public static final OfficialComponent DB2_JDBC_DRIVER = new OfficialComponent(155, "Db2-jdbc-driver"); + + public static final OfficialComponent SYBASE_JDBC_DRIVER = new OfficialComponent(156, "Sybase-jdbc-driver"); + + public static final OfficialComponent OCEANBASE_JDBC_DRIVER = new OfficialComponent(157, "OceanBase-jdbc-driver"); + + } diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/Db2URLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/Db2URLParser.java new file mode 100644 index 0000000000..8fe2b36515 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/Db2URLParser.java @@ -0,0 +1,129 @@ +/* + * 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.jdbc.connectionurl.parser; + +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +public class Db2URLParser extends AbstractURLParser { + private static final String DEFAULT_HOST = "localhost"; + private static final int DEFAULT_PORT = 50000; + private static final String DB_TYPE = "DB2"; + private static final String JDBC_PREFIX = "jdbc:db2:"; + + public Db2URLParser(String url) { + super(url); + } + + @Override + protected URLLocation fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("//"); + if (hostLabelStartIndex == -1) { + return null; + } + int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); + int hostLabelEndIndexWithParameter = url.indexOf(":", hostLabelEndIndex + 1); + if (hostLabelEndIndex == -1) { + hostLabelEndIndex = hostLabelEndIndexWithParameter; + } + if (hostLabelEndIndexWithParameter < hostLabelEndIndex && hostLabelEndIndexWithParameter != -1) { + hostLabelEndIndex = hostLabelEndIndexWithParameter; + } + if (hostLabelEndIndex == -1) { + hostLabelEndIndex = url.length(); + } + return new URLLocation(hostLabelStartIndex + 2, hostLabelEndIndex); + } + + protected String fetchDatabaseNameFromURL(int startSize) { + URLLocation hostsLocation = fetchDatabaseNameIndexRange(startSize); + if (hostsLocation == null) { + return ""; + } + return url.substring(hostsLocation.startIndex(), hostsLocation.endIndex()); + } + + protected URLLocation fetchDatabaseNameIndexRange(int startSize) { + int databaseStartTag = url.indexOf("/", startSize); + int parameterStartTag = url.indexOf(":", startSize); + if (parameterStartTag < databaseStartTag && parameterStartTag != -1) { + return null; + } + if (databaseStartTag == -1) { + databaseStartTag = startSize - 1; + } + int databaseEndTag = url.indexOf(":", startSize); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new URLLocation(databaseStartTag + 1, databaseEndTag); + } + + @Override + protected URLLocation fetchDatabaseNameIndexRange() { + int databaseStartTag = url.lastIndexOf("/"); + int databaseEndTag = url.indexOf(":", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new URLLocation(databaseStartTag + 1, databaseEndTag); + } + + @Override + public ConnectionInfo parse() { + URLLocation location = fetchDatabaseHostsIndexRange(); + if (location == null) { + return new ConnectionInfo( + ComponentsDefine.DB2_JDBC_DRIVER, DB_TYPE, DEFAULT_HOST, DEFAULT_PORT, + fetchDatabaseNameFromURL(JDBC_PREFIX.length()) + ); + } + String hosts = url.substring(location.startIndex(), location.endIndex()); + String[] hostSegment = hosts.split(","); + if (hostSegment.length > 1) { + StringBuilder sb = new StringBuilder(); + for (String host : hostSegment) { + if (host.split(":").length == 1) { + sb.append(host).append(":").append(DEFAULT_PORT).append(","); + } else { + sb.append(host).append(","); + } + } + return new ConnectionInfo( + ComponentsDefine.DB2_JDBC_DRIVER, DB_TYPE, sb.substring(0, sb.length() - 1), + fetchDatabaseNameFromURL() + ); + } else { + String[] hostAndPort = hostSegment[0].split(":"); + if (hostAndPort.length != 1) { + return new ConnectionInfo( + ComponentsDefine.DB2_JDBC_DRIVER, DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), + fetchDatabaseNameFromURL(location + .endIndex()) + ); + } else { + return new ConnectionInfo( + ComponentsDefine.DB2_JDBC_DRIVER, DB_TYPE, hostAndPort[0], DEFAULT_PORT, + fetchDatabaseNameFromURL(location + .endIndex()) + ); + } + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/DerbyURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/DerbyURLParser.java new file mode 100644 index 0000000000..dd96b8e06a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/DerbyURLParser.java @@ -0,0 +1,197 @@ +/* + * 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.jdbc.connectionurl.parser; + +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +public class DerbyURLParser extends AbstractURLParser { + + private static final String DEFAULT_HOST = "localhost"; + private static final int DEFAULT_PORT = 1527; + private static final String DB_TYPE = "Derby"; + private static final String DERBY_JDBC_URL_PREFIX = "jdbc:derby"; + /** + * Flag that running with directory mode. + */ + private static final String DIRECTORY_MODE_FLAG = "derby:directory"; + /** + * Flag that running with memory mode. + */ + private static final String MEMORY_MODE_FLAG = "derby:memory"; + /** + * Flag that running with classpath mode. + */ + private static final String CLASSPATH_MODE_FLAG = "derby:classpath"; + /** + * Flag that running with jar mode. + */ + private static final String JAR_MODE_FLAG = "derby:jar"; + + public DerbyURLParser(String url) { + super(url); + } + + /** + * Fetch range index that the database name from connection url if Derby database running in client/server + * environment. eg: jdbc:derby://host[:port]/[databaseName][;attribute=value]* + * + * @return range index that the database name. + */ + @Override + protected URLLocation fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("//"); + int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); + return new URLLocation(hostLabelStartIndex + 2, hostLabelEndIndex); + } + + @Override + protected URLLocation fetchDatabaseNameIndexRange() { + int databaseEndTag = url.indexOf(";"); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + int databaseStartTag = url.lastIndexOf("\\"); + if (databaseStartTag == -1) { + databaseStartTag = url.lastIndexOf("/"); + } + if (url.indexOf(":", databaseStartTag) != -1) { + databaseStartTag = url.indexOf(":", databaseStartTag); + } + return new URLLocation(databaseStartTag + 1, databaseEndTag); + } + + @Override + public ConnectionInfo parse() { + int[] databaseNameRangeIndex = fetchDatabaseNameRangeIndexForSubProtocol(DIRECTORY_MODE_FLAG); + if (databaseNameRangeIndex != null) { + return defaultConnection(databaseNameRangeIndex); + } + databaseNameRangeIndex = fetchDatabaseNameRangeIndexForSubProtocol(MEMORY_MODE_FLAG); + if (databaseNameRangeIndex != null) { + return defaultConnection(databaseNameRangeIndex); + } + databaseNameRangeIndex = fetchDatabaseNameRangeIndexForSubProtocol(CLASSPATH_MODE_FLAG); + if (databaseNameRangeIndex != null) { + return defaultConnection(databaseNameRangeIndex); + } + databaseNameRangeIndex = fetchDatabaseNameRangeIndexForSubProtocol(JAR_MODE_FLAG); + if (databaseNameRangeIndex != null) { + return defaultConnection(databaseNameRangeIndex); + } + databaseNameRangeIndex = fetchDatabaseNameRangeIndexWithoutHosts(); + if (databaseNameRangeIndex != null) { + return defaultConnection(databaseNameRangeIndex); + } + String[] hostAndPort = fetchDatabaseHostsFromURL().split(":"); + if (hostAndPort.length == 1) { + return new ConnectionInfo( + ComponentsDefine.DERBY_JDBC_DRIVER, DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL()); + } else { + return new ConnectionInfo( + ComponentsDefine.DERBY_JDBC_DRIVER, DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), + fetchDatabaseNameFromURL() + ); + } + } + + /** + * Fetch range index that the database name from connection url if Derby database running in embedded environment. + * eg: jdbc:derby:[databaseName][;attribute=value]* + * + * @return range index that the database name. + */ + private int[] fetchDatabaseNameRangeIndexWithoutHosts() { + if (url.contains("//")) { + return null; + } + int fileLabelIndex = url.indexOf(DERBY_JDBC_URL_PREFIX); + int parameterLabelIndex = url.indexOf(";"); + if (parameterLabelIndex == -1) { + parameterLabelIndex = url.length(); + } + + if (fileLabelIndex != -1) { + int pathLabelIndexForLinux = url.lastIndexOf("/"); + if (pathLabelIndexForLinux != -1 && pathLabelIndexForLinux > fileLabelIndex) { + return new int[] { + pathLabelIndexForLinux + 1, + parameterLabelIndex + }; + } + int pathLabelIndexForWin = url.lastIndexOf("\\"); + if (pathLabelIndexForWin != -1 && pathLabelIndexForWin > fileLabelIndex) { + return new int[] { + pathLabelIndexForWin + 1, + parameterLabelIndex + }; + } + return new int[] { + fileLabelIndex + DERBY_JDBC_URL_PREFIX.length() + 1, + parameterLabelIndex + }; + } else { + return null; + } + } + + /** + * Fetch range index that the database name from connection url if Derby database running with subprotocol. eg: + * jdbc:derby:subprotocol:[databaseName][;attribute=value]* + * + * @return range index that the database name. + */ + private int[] fetchDatabaseNameRangeIndexForSubProtocol(String mode) { + int fileLabelIndex = url.indexOf(mode); + int parameterLabelIndex = url.indexOf(";", fileLabelIndex); + if (parameterLabelIndex == -1) { + parameterLabelIndex = url.length(); + } + + if (fileLabelIndex != -1) { + int pathLabelIndexForLinux = url.lastIndexOf("/"); + if (pathLabelIndexForLinux != -1 && pathLabelIndexForLinux > fileLabelIndex) { + return new int[] { + pathLabelIndexForLinux + 1, + parameterLabelIndex + }; + } + int pathLabelIndexForWin = url.lastIndexOf("\\"); + if (pathLabelIndexForWin != -1 && pathLabelIndexForWin > fileLabelIndex) { + return new int[] { + pathLabelIndexForWin + 1, + parameterLabelIndex + }; + } + return new int[] { + fileLabelIndex + mode.length() + 1, + parameterLabelIndex + }; + } else { + return null; + } + } + + private ConnectionInfo defaultConnection(int[] databaseNameRangeIndex) { + return new ConnectionInfo( + ComponentsDefine.DERBY_JDBC_DRIVER, DB_TYPE, DEFAULT_HOST, -1, + fetchDatabaseNameFromURL(databaseNameRangeIndex) + ); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/OceanBaseURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/OceanBaseURLParser.java new file mode 100644 index 0000000000..f459c268e8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/OceanBaseURLParser.java @@ -0,0 +1,27 @@ +/* + * 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.jdbc.connectionurl.parser; + +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; + +public class OceanBaseURLParser extends MysqlURLParser { + public OceanBaseURLParser(String url) { + super(url, "OceanBase", ComponentsDefine.OCEANBASE_JDBC_DRIVER, 2881); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/SqliteURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/SqliteURLParser.java new file mode 100644 index 0000000000..21f44492b3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/SqliteURLParser.java @@ -0,0 +1,57 @@ +/* + * 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.jdbc.connectionurl.parser; + +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +public class SqliteURLParser extends AbstractURLParser { + private static final String DEFAULT_HOST = "localhost"; + private static final int DEFAULT_PORT = -1; + private static final String DB_TYPE = "Sqlite"; + + public SqliteURLParser(String url) { + super(url); + } + + @Override + protected URLLocation fetchDatabaseHostsIndexRange() { + return null; + } + + @Override + protected URLLocation fetchDatabaseNameIndexRange() { + int databaseStartTag = url.lastIndexOf("/"); + if (databaseStartTag == -1) { + databaseStartTag = url.lastIndexOf(":"); + } + int databaseEndTag = url.indexOf("?"); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + + return new URLLocation(databaseStartTag + 1, databaseEndTag); + } + + @Override + public ConnectionInfo parse() { + return new ConnectionInfo( + ComponentsDefine.SQLITE_JDBC_DRIVER, DB_TYPE, DEFAULT_HOST, DEFAULT_PORT, fetchDatabaseNameFromURL()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/SybaseURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/SybaseURLParser.java new file mode 100644 index 0000000000..dfc8a57519 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/SybaseURLParser.java @@ -0,0 +1,114 @@ +/* + * 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.jdbc.connectionurl.parser; + +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +public class SybaseURLParser extends AbstractURLParser { + private static final int DEFAULT_PORT = 5000; + private static final String DB_TYPE = "Sybase"; + private static final String JDBC_PREFIX = "jdbc:sybase:Tds:"; + + public SybaseURLParser(String url) { + super(url); + } + + @Override + protected URLLocation fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = JDBC_PREFIX.length(); + int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex); + int hostLabelEndIndexWithParameter = url.indexOf("?", hostLabelStartIndex); + if (hostLabelEndIndex == -1) { + hostLabelEndIndex = hostLabelEndIndexWithParameter; + } + if (hostLabelEndIndexWithParameter < hostLabelEndIndex && hostLabelEndIndexWithParameter != -1) { + hostLabelEndIndex = hostLabelEndIndexWithParameter; + } + if (hostLabelEndIndex == -1) { + hostLabelEndIndex = url.length(); + } + return new URLLocation(hostLabelStartIndex, hostLabelEndIndex); + } + + protected String fetchDatabaseNameFromURL(int startSize) { + URLLocation hostsLocation = fetchDatabaseNameIndexRange(startSize); + if (hostsLocation == null) { + return ""; + } + return url.substring(hostsLocation.startIndex(), hostsLocation.endIndex()); + } + + protected URLLocation fetchDatabaseNameIndexRange(int startSize) { + int databaseStartTag = url.indexOf("/", startSize); + int parameterStartTag = url.indexOf("?", startSize); + if (parameterStartTag < databaseStartTag && parameterStartTag != -1) { + return null; + } + if (databaseStartTag == -1) { + return null; + } + int databaseEndTag = url.indexOf("?", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new URLLocation(databaseStartTag + 1, databaseEndTag); + } + + @Override + protected URLLocation fetchDatabaseNameIndexRange() { + int databaseStartTag = url.lastIndexOf("/"); + int databaseEndTag = url.indexOf("?", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new URLLocation(databaseStartTag + 1, databaseEndTag); + } + + @Override + public ConnectionInfo parse() { + URLLocation location = fetchDatabaseHostsIndexRange(); + String hosts = url.substring(location.startIndex(), location.endIndex()); + String[] hostSegment = hosts.split(","); + if (hostSegment.length > 1) { + StringBuilder sb = new StringBuilder(); + for (String host : hostSegment) { + if (host.split(":").length == 1) { + sb.append(host).append(":").append(DEFAULT_PORT).append(","); + } else { + sb.append(host).append(","); + } + } + return new ConnectionInfo(ComponentsDefine.SYBASE_JDBC_DRIVER, DB_TYPE, sb.substring(0, sb.length() - 1), fetchDatabaseNameFromURL()); + } else { + String[] hostAndPort = hostSegment[0].split(":"); + if (hostAndPort.length != 1) { + return new ConnectionInfo( + ComponentsDefine.SYBASE_JDBC_DRIVER, DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), + fetchDatabaseNameFromURL(location + .endIndex()) + ); + } else { + return new ConnectionInfo( + ComponentsDefine.SYBASE_JDBC_DRIVER, DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL(location + .endIndex())); + } + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java index eab319fd7e..cb79d58b0c 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java @@ -36,6 +36,11 @@ public class URLParser { private static final String KYLIN_JDBC_URL_PREFIX = "jdbc:kylin"; private static final String IMPALA_JDBC_URL_PREFIX = "jdbc:impala"; private static final String CLICKHOUSE_JDBC_URL_PREFIX = "jdbc:clickhouse"; + private static final String DERBY_JDBC_URL_PREFIX = "jdbc:derby:"; + private static final String SQLITE_JDBC_URL_PREFIX = "jdbc:sqlite:"; + private static final String DB2_JDBC_URL_PREFIIX = "jdbc:db2:"; + private static final String SYBASE_JDBC_URL_PREFIX = "jdbc:sybase:tds:"; + private static final String OCEANBASE_JDBC_URL_PREFIX = "jdbc:oceanbase:"; public static ConnectionInfo parser(String url) { ConnectionURLParser parser = null; @@ -60,6 +65,16 @@ public static ConnectionInfo parser(String url) { parser = new ImpalaJdbcURLParser(url); } else if (lowerCaseUrl.startsWith(CLICKHOUSE_JDBC_URL_PREFIX)) { parser = new ClickHouseURLParser(url); + } else if (lowerCaseUrl.startsWith(DERBY_JDBC_URL_PREFIX)) { + parser = new DerbyURLParser(url); + } else if (lowerCaseUrl.startsWith(SQLITE_JDBC_URL_PREFIX)) { + parser = new SqliteURLParser(url); + } else if (lowerCaseUrl.startsWith(DB2_JDBC_URL_PREFIIX)) { + parser = new Db2URLParser(url); + } else if (lowerCaseUrl.startsWith(SYBASE_JDBC_URL_PREFIX)) { + parser = new SybaseURLParser(url); + } else if (lowerCaseUrl.startsWith(OCEANBASE_JDBC_URL_PREFIX)) { + parser = new OceanBaseURLParser(url); } return parser.parse(); } diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java index f679f05cdf..48715ad840 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java @@ -280,4 +280,139 @@ public void testParsePostgresqlJDBCURLWithMultiIpv6() { assertThat(connectionInfo.getDatabaseName(), is("testdb")); assertThat(connectionInfo.getDatabasePeer(), is("[2001:db8::1234]:5432,[2001:db8::1235]:5432")); } -} + + @Test + public void testParseOceanBaseJDBCURL() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:oceanbase://localhost:2881/mydb?user=root@sys&password=pass&pool=false&useBulkStmts=true&rewriteBatchedStatements=false&useServerPrepStmts=true"); + assertThat(connectionInfo.getDBType(), is("OceanBase")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:2881")); + } + + @Test + public void testParseOceanBaseJDBCURLWithMultiHosts() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:oceanbase://primaryhost:2888,secondaryhost1,secondaryhost2/mydb?user=root@sys&password=pass&pool=false&useBulkStmts=true&rewriteBatchedStatements=false&useServerPrepStmts=true"); + assertThat(connectionInfo.getDBType(), is("OceanBase")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:2888,secondaryhost1:2881,secondaryhost2:2881")); + } + + @Test + public void testParseDerbyJDBCURLWithDirMode() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:derby:directory:mydb"); + assertThat(connectionInfo.getDBType(), is("Derby")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); + } + + @Test + public void testParseDerbyJDBCURLWithMemMode() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:derby:memory:mydb;create=true"); + assertThat(connectionInfo.getDBType(), is("Derby")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); + } + + @Test + public void testParseDerbyJDBCURLWithClassPathMode() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:derby:classpath:/test/mydb"); + assertThat(connectionInfo.getDBType(), is("Derby")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); + } + + @Test + public void testParseDerbyJDBCURLWithJarMode() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:derby:jar:(C:/dbs.jar)test/mydb"); + assertThat(connectionInfo.getDBType(), is("Derby")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); + } + + @Test + public void testParseDerbyJDBCURLWithEmbeddedMode() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:derby:test/mydb;create=true"); + assertThat(connectionInfo.getDBType(), is("Derby")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); + } + + @Test + public void testParseDerbyJDBCURLWithMemModeAndClientServerMode() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:derby://localhost:1527/memory:/test/mydb;create=true"); + assertThat(connectionInfo.getDBType(), is("Derby")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:1527")); + } + + @Test + public void testParseDerbyJDBCURLWithClientServerMode() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:derby://localhost:1527/mydb;create=true;user=root;password=pass"); + assertThat(connectionInfo.getDBType(), is("Derby")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:1527")); + } + + @Test + public void testParseDB2JDBCURL() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:db2://localhost:50000/mydb:user=root;password=pass"); + assertThat(connectionInfo.getDBType(), is("DB2")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:50000")); + } + + @Test + public void testParseDB2JDBCURLWithoutHost() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:db2:mydb:user=root;password=pass"); + assertThat(connectionInfo.getDBType(), is("DB2")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:50000")); + } + + @Test + public void testParseSqliteJDBCURL() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:sqlite:C/test/mydb.db"); + assertThat(connectionInfo.getDBType(), is("Sqlite")); + assertThat(connectionInfo.getDatabaseName(), is("mydb.db")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); + } + + @Test + public void testParseSqliteJDBCURLWithMem() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:sqlite::memory:?jdbc.explicit_readonly=true"); + assertThat(connectionInfo.getDBType(), is("Sqlite")); + assertThat(connectionInfo.getDatabaseName(), is("")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); + } + + @Test + public void testParseSqliteJDBCURLWithResource() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:sqlite::resource:org/test/mydb.db"); + assertThat(connectionInfo.getDBType(), is("Sqlite")); + assertThat(connectionInfo.getDatabaseName(), is("mydb.db")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); + } + + @Test + public void testParseSybaseJDBCURL() { + ConnectionInfo connectionInfo = new URLParser().parser( + "jdbc:sybase:Tds:localhost:5000/mydb?charset=utf-8"); + assertThat(connectionInfo.getDBType(), is("Sybase")); + assertThat(connectionInfo.getDatabaseName(), is("mydb")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:5000")); + } +} \ No newline at end of file diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index a51d267460..9b21ea11d8 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -168,10 +168,27 @@ The meter plugin provides the advanced metrics collections, which are not a part * [Jetty](https://github.com/eclipse/jetty.project) 9.1.x -> 11.x * [Grizzly](https://github.com/eclipse-ee4j/grizzly) 2.3.x -> 4.x * Connection Pool - * [Apache Commons DBCP](https://github.com/apache/commons-dbcp) 2.x - * [Alibaba Druid](https://github.com/alibaba/druid) 1.x - * [HikariCP](https://github.com/brettwooldridge/HikariCP) 3.x -> 4.x - * [C3P0](https://github.com/swaldman/c3p0) 0.9.0 -> 0.10.0 + * Supported JDBC drviers + * [MySQL](https://www.mysql.com/) + * [Oracle](https://www.oracle.com/) + * [H2](https://h2database.com/html/main.html) + * [PostgreSQL](https://www.postgresql.org/) + * [MariaDB](https://mariadb.org/) + * [SQL Server](https://www.microsoft.com/en-us/sql-server/) + * [Apache Kylin](https://kylin.apache.org/) + * [Impala](https://impala.apache.org/) + * [ClickHouse](https://clickhouse.com/) + * [Derby](https://db.apache.org/derby/) + * [SQLite](https://www.sqlite.org/index.html) + * [DB2](https://www.ibm.com/products/db2/database) + * Sybase + * [OceanBase](https://www.oceanbase.com/) + * Supported Connection Pool Frameworks + * [Apache Commons DBCP](https://github.com/apache/commons-dbcp) 2.x + * [Alibaba Druid](https://github.com/alibaba/druid) 1.x + * [HikariCP](https://github.com/brettwooldridge/HikariCP) 3.x -> 4.x + * [C3P0](https://github.com/swaldman/c3p0) 0.9.0 -> 0.10.0 + ___ ¹Due to license incompatibilities/restrictions these plugins are hosted and released in 3rd part repository, go to [SkyAPM java plugin extension repository](https://github.com/SkyAPM/java-plugin-extensions) to get these. From 0bf535e861389fcd82f82f0dd3f1aade6a3dac3f Mon Sep 17 00:00:00 2001 From: jiangyuan Date: Sun, 12 May 2024 11:37:55 +0800 Subject: [PATCH 012/114] Fix TracingSegmentRunner (testing only) (#688) --- .../apm/agent/core/test/tools/TracingSegmentRunner.java | 4 +++- .../skywalking/apm/agent/test/tools/TracingSegmentRunner.java | 4 +++- ...eterContextSnapshotThreadLocalAccessorInterceptorTest.java | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/test/tools/TracingSegmentRunner.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/test/tools/TracingSegmentRunner.java index 1b88070fda..a9fa848e21 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/test/tools/TracingSegmentRunner.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/test/tools/TracingSegmentRunner.java @@ -55,7 +55,7 @@ protected Object createTest() throws Exception { @Override protected Statement withAfters(FrameworkMethod method, Object target, final Statement statement) { - return new Statement() { + Statement st = new Statement() { @Override public void evaluate() throws Throwable { if (field != null) { @@ -89,5 +89,7 @@ public void afterFinished(IgnoredTracerContext tracerContext) { } } }; + + return super.withAfters(method, target, st); } } diff --git a/apm-sniffer/apm-test-tools/src/main/java/org/apache/skywalking/apm/agent/test/tools/TracingSegmentRunner.java b/apm-sniffer/apm-test-tools/src/main/java/org/apache/skywalking/apm/agent/test/tools/TracingSegmentRunner.java index 0626f36d01..8dbb6cf1a3 100644 --- a/apm-sniffer/apm-test-tools/src/main/java/org/apache/skywalking/apm/agent/test/tools/TracingSegmentRunner.java +++ b/apm-sniffer/apm-test-tools/src/main/java/org/apache/skywalking/apm/agent/test/tools/TracingSegmentRunner.java @@ -55,7 +55,7 @@ protected Object createTest() throws Exception { @Override protected Statement withAfters(FrameworkMethod method, Object target, final Statement statement) { - return new Statement() { + Statement st = new Statement() { @Override public void evaluate() throws Throwable { if (field != null) { @@ -89,5 +89,7 @@ public void afterFinished(IgnoredTracerContext tracerContext) { } } }; + + return super.withAfters(method, target, st); } } diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/micrometer/MicrometerContextSnapshotThreadLocalAccessorInterceptorTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/micrometer/MicrometerContextSnapshotThreadLocalAccessorInterceptorTest.java index 3e3f66c844..258808f8f1 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/micrometer/MicrometerContextSnapshotThreadLocalAccessorInterceptorTest.java +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/micrometer/MicrometerContextSnapshotThreadLocalAccessorInterceptorTest.java @@ -92,8 +92,6 @@ public void clear() { @AfterClass public static void clearAfterAll() { // test from threadlocalaccessor test x 2 TODO: I have no idea what is going on - ContextManager.stopSpan(); - ContextManager.stopSpan(); assertThat(ContextManager.isActive(), is(false)); } @@ -103,6 +101,7 @@ public void testServiceFromPlugin() { PluginBootService.class); Assert.assertNotNull(service); + ContextManager.stopSpan(); } @Test @@ -110,6 +109,7 @@ public void testServiceOverrideFromPlugin() { ContextManagerExtendService service = ServiceManager.INSTANCE.findService(ContextManagerExtendService.class); Assert.assertTrue(service instanceof ContextManagerExtendOverrideService); + ContextManager.stopSpan(); } @Test From 4dfc1e85b56e75a1bf2bae11d34d8c0fe234bed0 Mon Sep 17 00:00:00 2001 From: Chen Ziyan Date: Tue, 14 May 2024 20:21:27 +0800 Subject: [PATCH 013/114] Fix method name missing in spring-plugins:scheduled-annotation-plugin with spring 6.1.x (#691) --- .github/workflows/plugins-jdk17-test.1.yaml | 1 + .github/workflows/plugins-test.3.yaml | 2 +- CHANGES.md | 1 + ...duledMethodInterceptorInstrumentation.java | 13 ++ .../java-agent/Supported-list.md | 2 +- .../java/controller/MessageService.java | 43 +++++-- .../config/expectedData.yaml | 68 +++++++++++ .../configuration.yml | 19 +++ .../pom.xml | 8 +- .../scheduled/controller/CaseController.java | 0 .../spring/scheduled/job/SchedulingJob.java | 48 ++++++++ .../src/main/resources/log4j2.xml | 0 .../webapp/WEB-INF/spring-mvc-servlet.xml | 0 .../src/main/webapp/WEB-INF/web.xml | 34 ++++++ .../support-version.list | 3 +- .../config/expectedData.yaml | 10 +- .../configuration.yml | 4 +- .../spring-scheduled-6.x-scenario/pom.xml | 112 ++++++++++++++++++ .../scheduled/controller/CaseController.java | 46 +++++++ .../spring/scheduled/job/SchedulingJob.java | 2 +- .../src/main/resources/log4j2.xml | 30 +++++ .../webapp/WEB-INF/spring-mvc-servlet.xml | 38 ++++++ .../src/main/webapp/WEB-INF/web.xml | 2 +- .../support-version.list | 18 +++ 24 files changed, 475 insertions(+), 29 deletions(-) create mode 100644 test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/configuration.yml rename test/plugin/scenarios/{spring-scheduled-scenario => spring-scheduled-3.x-5.x-scenario}/pom.xml (94%) rename test/plugin/scenarios/{spring-scheduled-scenario => spring-scheduled-3.x-5.x-scenario}/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/controller/CaseController.java (100%) create mode 100644 test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java rename test/plugin/scenarios/{spring-scheduled-scenario => spring-scheduled-3.x-5.x-scenario}/src/main/resources/log4j2.xml (100%) rename test/plugin/scenarios/{spring-scheduled-scenario => spring-scheduled-3.x-5.x-scenario}/src/main/webapp/WEB-INF/spring-mvc-servlet.xml (100%) create mode 100644 test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/webapp/WEB-INF/web.xml rename test/plugin/scenarios/{spring-scheduled-scenario => spring-scheduled-3.x-5.x-scenario}/support-version.list (97%) rename test/plugin/scenarios/{spring-scheduled-scenario => spring-scheduled-6.x-scenario}/config/expectedData.yaml (91%) rename test/plugin/scenarios/{spring-scheduled-scenario => spring-scheduled-6.x-scenario}/configuration.yml (82%) create mode 100644 test/plugin/scenarios/spring-scheduled-6.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/controller/CaseController.java rename test/plugin/scenarios/{spring-scheduled-scenario => spring-scheduled-6.x-scenario}/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java (96%) create mode 100644 test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml rename test/plugin/scenarios/{spring-scheduled-scenario => spring-scheduled-6.x-scenario}/src/main/webapp/WEB-INF/web.xml (95%) create mode 100644 test/plugin/scenarios/spring-scheduled-6.x-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index 61bb8fa75a..949e69cfa1 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -62,6 +62,7 @@ jobs: - activemq-artemis-2.x-scenario - c3p0-0.9.0.x-0.9.1.x-scenario - c3p0-0.9.2.x-0.10.x-scenario + - spring-scheduled-6.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index 7451dcf4b5..e687161731 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -81,7 +81,7 @@ jobs: - spring-kafka-1.3.x-scenario - spring-kafka-2.2.x-scenario - spring-kafka-2.3.x-scenario - - spring-scheduled-scenario + - spring-scheduled-3.x-5.x-scenario - elasticjob-2.x-scenario - quartz-scheduler-2.x-scenario - xxl-job-2.2.0-scenario diff --git a/CHANGES.md b/CHANGES.md index 6b6c759ae5..0340de503d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Release Notes. * Use a daemon thread to flush logs. * Fix typos in `URLParser`. * Add support for `Derby`/`Sybase`/`SQLite`/`DB2`/`OceanBase` jdbc url format in `URLParser`. +* Optimize spring-plugins:scheduled-annotation-plugin compatibility about Spring 6.1.x support. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/scheduled/define/ScheduledMethodInterceptorInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/scheduled/define/ScheduledMethodInterceptorInstrumentation.java index 2aacd3720b..44b36778bb 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/scheduled/define/ScheduledMethodInterceptorInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/scheduled/define/ScheduledMethodInterceptorInstrumentation.java @@ -82,6 +82,19 @@ public ElementMatcher getConstructorMatcher() { public String getConstructorInterceptor() { return CONSTRUCTOR_WITH_STRING_INTERCEPTOR_CLASS; } + }, + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(4) + .and(takesArgument(0, Object.class)) + .and(takesArgument(1, Method.class)); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_METHOD_INTERCEPTOR_CLASS; + } } }; } diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 9b21ea11d8..1fa2672282 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -120,7 +120,7 @@ metrics based on the tracing data. * Scheduler * [Elastic Job](https://github.com/elasticjob/elastic-job) 2.x * [Apache ShardingSphere-Elasticjob](https://github.com/apache/shardingsphere-elasticjob) 3.x - * [Spring @Scheduled](https://github.com/spring-projects/spring-framework) 3.1+ + * [Spring @Scheduled](https://github.com/spring-projects/spring-framework) 3.1.x -> 6.1.x * [Quartz Scheduler](https://github.com/quartz-scheduler/quartz) 2.x (Optional²) * [XXL Job](https://github.com/xuxueli/xxl-job) 2.x * OpenTracing community supported diff --git a/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/MessageService.java b/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/MessageService.java index 0c87f66981..f7d4dc3c9b 100644 --- a/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/MessageService.java +++ b/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/MessageService.java @@ -87,8 +87,8 @@ public void sendNormalMessageAsync(String topic, String tag, String group) throw .build(); try { CompletableFuture future = producer.sendAsync(message); - future.join(); - log.info("Send async message successfully"); + SendReceipt sendReceipt = future.join(); + log.info("Send async message successfully, messageId={}", sendReceipt.getMessageId()); } catch (Throwable t) { log.error("Failed to send message", t); } @@ -142,17 +142,34 @@ public void simpleConsumes(List topics, .build(); Duration invisibleDuration = Duration.ofSeconds(duration); - final List messages = consumer.receive(maxMessageNum, invisibleDuration); - messages.forEach(messageView -> { - log.info("Received message: {}", messageView); - }); - for (MessageView msg : messages) { - final MessageId messageId = msg.getMessageId(); - try { - consumer.ack(msg); - log.info("Message is acknowledged successfully, messageId={}", messageId); - } catch (Throwable t) { - log.error("Message is failed to be acknowledged, messageId={}", messageId, t); + int counter = 0; + int checkCounter = 0; + while (true) { + final List messages = consumer.receive(maxMessageNum, invisibleDuration); + messages.forEach(messageView -> { + log.info("Received message: {}", messageView); + }); + boolean finishFlag = false; + for (MessageView msg : messages) { + final MessageId messageId = msg.getMessageId(); + try { + consumer.ack(msg); + log.info("Message is acknowledged successfully, messageId={}", messageId); + counter++; + if (counter >= 2) { + finishFlag = true; + } + } catch (Throwable t) { + log.error("Message is failed to be acknowledged, messageId={}", messageId, t); + } + } + checkCounter++; + if (finishFlag) { + break; + } + if (checkCounter >= 3) { + log.error("Message is failed to receive after 3 attempts"); + break; } } } catch (Exception e) { diff --git a/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..285bb6bd3e --- /dev/null +++ b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/config/expectedData.yaml @@ -0,0 +1,68 @@ +# 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: spring-scheduled-3.x-5.x-scenario + segmentSize: ge 2 + segments: + - segmentId: not null + spans: + - operationName: GET:/spring-scheduled-3.x-5.x-scenario/case/call + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/spring-scheduled-3.x-5.x-scenario/case/call'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: SpringScheduled/org.apache.skywalking.apm.testcase.spring.scheduled.job.SchedulingJob.work, networkAddress: 'localhost:8080', refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} + - segmentId: not null + spans: + - operationName: /spring-scheduled-3.x-5.x-scenario/case/call + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-scheduled-3.x-5.x-scenario/case/call'} + - {key: http.status_code, value: '200'} + - operationName: SpringScheduled/org.apache.skywalking.apm.testcase.spring.scheduled.job.SchedulingJob.work + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: not null + endTime: not null + componentId: 96 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: x-le, value: '{"logic-span":true}'} diff --git a/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/configuration.yml b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/configuration.yml new file mode 100644 index 0000000000..61cc0a3fb3 --- /dev/null +++ b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/configuration.yml @@ -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. + +type: tomcat +entryService: http://localhost:8080/spring-scheduled-3.x-5.x-scenario/case/healthCheck +healthCheck: http://localhost:8080/spring-scheduled-3.x-5.x-scenario/case/healthCheck \ No newline at end of file diff --git a/test/plugin/scenarios/spring-scheduled-scenario/pom.xml b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/pom.xml similarity index 94% rename from test/plugin/scenarios/spring-scheduled-scenario/pom.xml rename to test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/pom.xml index 10f388f6ac..8dd8e29cbe 100644 --- a/test/plugin/scenarios/spring-scheduled-scenario/pom.xml +++ b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/pom.xml @@ -21,13 +21,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> org.apache.skywalking.apm.testcase - spring-scheduled-scenario + spring-scheduled-3.x-5.x-scenario 1.0.0 war 4.0.0 - skywalking-spring-scheduled-scenario + skywalking-spring-scheduled-3.x-5.x-scenario UTF-8 @@ -92,7 +92,7 @@ - spring-scheduled-scenario + spring-scheduled-3.x-5.x-scenario maven-compiler-plugin @@ -109,7 +109,7 @@ 2.1 8080 - /spring-scheduled-scenario + /spring-scheduled-3.x-5.x-scenario UTF-8 tomcat7 diff --git a/test/plugin/scenarios/spring-scheduled-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/controller/CaseController.java b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/controller/CaseController.java similarity index 100% rename from test/plugin/scenarios/spring-scheduled-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/controller/CaseController.java rename to test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/controller/CaseController.java diff --git a/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java new file mode 100644 index 0000000000..c943af8a56 --- /dev/null +++ b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java @@ -0,0 +1,48 @@ +/* + * 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.testcase.spring.scheduled.job; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +import java.io.IOException; + +@Configuration +@EnableScheduling +public class SchedulingJob { + + private static final Logger LOGGER = LogManager.getLogger(SchedulingJob.class); + + private static final OkHttpClient CLIENT = new OkHttpClient.Builder().build(); + + @Scheduled(fixedDelay = 5000) + public void work() throws IOException { + LOGGER.info("work job running!"); + + Request request = new Request.Builder().url("http://localhost:8080/spring-scheduled-3.x-5.x-scenario/case/call").build(); + Response response = CLIENT.newCall(request).execute(); + response.body().close(); + } +} diff --git a/test/plugin/scenarios/spring-scheduled-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/resources/log4j2.xml similarity index 100% rename from test/plugin/scenarios/spring-scheduled-scenario/src/main/resources/log4j2.xml rename to test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/resources/log4j2.xml diff --git a/test/plugin/scenarios/spring-scheduled-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml similarity index 100% rename from test/plugin/scenarios/spring-scheduled-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml rename to test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml diff --git a/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/webapp/WEB-INF/web.xml b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..041c8b4f29 --- /dev/null +++ b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,34 @@ + + + skywalking-spring-scheduled-3.x-5.x-scenario + + + spring-mvc + org.springframework.web.servlet.DispatcherServlet + 1 + + + spring-mvc + / + + diff --git a/test/plugin/scenarios/spring-scheduled-scenario/support-version.list b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/support-version.list similarity index 97% rename from test/plugin/scenarios/spring-scheduled-scenario/support-version.list rename to test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/support-version.list index 78ff603b37..9685fe8ec3 100644 --- a/test/plugin/scenarios/spring-scheduled-scenario/support-version.list +++ b/test/plugin/scenarios/spring-scheduled-3.x-5.x-scenario/support-version.list @@ -22,4 +22,5 @@ 4.3.28.RELEASE 5.0.18.RELEASE 5.1.17.RELEASE -5.2.8.RELEASE +5.2.25.RELEASE +5.3.34 \ No newline at end of file diff --git a/test/plugin/scenarios/spring-scheduled-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-scheduled-6.x-scenario/config/expectedData.yaml similarity index 91% rename from test/plugin/scenarios/spring-scheduled-scenario/config/expectedData.yaml rename to test/plugin/scenarios/spring-scheduled-6.x-scenario/config/expectedData.yaml index 1c5f45888c..f0a297781f 100644 --- a/test/plugin/scenarios/spring-scheduled-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/spring-scheduled-6.x-scenario/config/expectedData.yaml @@ -14,12 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. segmentItems: -- serviceName: spring-scheduled-scenario +- serviceName: spring-scheduled-6.x-scenario segmentSize: ge 2 segments: - segmentId: not null spans: - - operationName: GET:/spring-scheduled-scenario/case/call + - operationName: GET:/spring-scheduled-6.x-scenario/case/call parentSpanId: -1 spanId: 0 spanLayer: Http @@ -31,14 +31,14 @@ segmentItems: peer: '' skipAnalysis: false tags: - - {key: url, value: 'http://localhost:8080/spring-scheduled-scenario/case/call'} + - {key: url, value: 'http://localhost:8080/spring-scheduled-6.x-scenario/case/call'} - {key: http.method, value: GET} - {key: http.status_code, value: '200'} refs: - {parentEndpoint: SpringScheduled/org.apache.skywalking.apm.testcase.spring.scheduled.job.SchedulingJob.work, networkAddress: 'localhost:8080', refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} - segmentId: not null spans: - - operationName: /spring-scheduled-scenario/case/call + - operationName: /spring-scheduled-6.x-scenario/case/call parentSpanId: 0 spanId: 1 spanLayer: Http @@ -51,7 +51,7 @@ segmentItems: skipAnalysis: false tags: - {key: http.method, value: GET} - - {key: url, value: 'http://localhost:8080/spring-scheduled-scenario/case/call'} + - {key: url, value: 'http://localhost:8080/spring-scheduled-6.x-scenario/case/call'} - {key: http.status_code, value: '200'} - operationName: SpringScheduled/org.apache.skywalking.apm.testcase.spring.scheduled.job.SchedulingJob.work parentSpanId: -1 diff --git a/test/plugin/scenarios/spring-scheduled-scenario/configuration.yml b/test/plugin/scenarios/spring-scheduled-6.x-scenario/configuration.yml similarity index 82% rename from test/plugin/scenarios/spring-scheduled-scenario/configuration.yml rename to test/plugin/scenarios/spring-scheduled-6.x-scenario/configuration.yml index 93a92b6b00..9fec8d6ef0 100644 --- a/test/plugin/scenarios/spring-scheduled-scenario/configuration.yml +++ b/test/plugin/scenarios/spring-scheduled-6.x-scenario/configuration.yml @@ -15,5 +15,5 @@ # limitations under the License. type: tomcat -entryService: http://localhost:8080/spring-scheduled-scenario/case/healthCheck -healthCheck: http://localhost:8080/spring-scheduled-scenario/case/healthCheck \ No newline at end of file +entryService: http://localhost:8080/spring-scheduled-6.x-scenario/case/healthCheck +healthCheck: http://localhost:8080/spring-scheduled-6.x-scenario/case/healthCheck \ No newline at end of file diff --git a/test/plugin/scenarios/spring-scheduled-6.x-scenario/pom.xml b/test/plugin/scenarios/spring-scheduled-6.x-scenario/pom.xml new file mode 100644 index 0000000000..273d32a00b --- /dev/null +++ b/test/plugin/scenarios/spring-scheduled-6.x-scenario/pom.xml @@ -0,0 +1,112 @@ + + + + + org.apache.skywalking.apm.testcase + spring-scheduled-6.x-scenario + 1.0.0 + war + + 4.0.0 + + skywalking-spring-scheduled-6.x-scenario + + + UTF-8 + 17 + 3.8.1 + 1.18.20 + 6.1.6 + spring-scheduled + + + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + provided + + + org.apache.logging.log4j + log4j-api + 2.8.1 + + + org.apache.logging.log4j + log4j-core + 2.8.1 + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + org.springframework + spring-context + ${test.framework.version} + + + org.springframework + spring-web + ${test.framework.version} + + + org.springframework + spring-webmvc + ${test.framework.version} + + + cglib + cglib + 2.2 + + + + com.squareup.okhttp3 + okhttp + 3.0.0 + + + + + spring-scheduled-6.x-scenario + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-war-plugin + 3.3.1 + + + + diff --git a/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/controller/CaseController.java b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/controller/CaseController.java new file mode 100644 index 0000000000..41dd892c59 --- /dev/null +++ b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/controller/CaseController.java @@ -0,0 +1,46 @@ +/* + * 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.testcase.spring.scheduled.controller; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping("/case") +public class CaseController { + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + private static final String SUCCESS = "Success"; + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + return SUCCESS; + } + + @RequestMapping("/call") + @ResponseBody + public String call() { + return SUCCESS; + } +} diff --git a/test/plugin/scenarios/spring-scheduled-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java similarity index 96% rename from test/plugin/scenarios/spring-scheduled-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java rename to test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java index dc36b167e6..fd2e65ec45 100644 --- a/test/plugin/scenarios/spring-scheduled-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java +++ b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/scheduled/job/SchedulingJob.java @@ -41,7 +41,7 @@ public class SchedulingJob { public void work() throws IOException { LOGGER.info("work job running!"); - Request request = new Request.Builder().url("http://localhost:8080/spring-scheduled-scenario/case/call").build(); + Request request = new Request.Builder().url("http://localhost:8080/spring-scheduled-6.x-scenario/case/call").build(); Response response = CLIENT.newCall(request).execute(); response.body().close(); } diff --git a/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..b16354bfa3 --- /dev/null +++ b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml new file mode 100644 index 0000000000..78ce64329d --- /dev/null +++ b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml @@ -0,0 +1,38 @@ + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/spring-scheduled-scenario/src/main/webapp/WEB-INF/web.xml b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/webapp/WEB-INF/web.xml similarity index 95% rename from test/plugin/scenarios/spring-scheduled-scenario/src/main/webapp/WEB-INF/web.xml rename to test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/webapp/WEB-INF/web.xml index 97967a024e..2bbdb36e96 100644 --- a/test/plugin/scenarios/spring-scheduled-scenario/src/main/webapp/WEB-INF/web.xml +++ b/test/plugin/scenarios/spring-scheduled-6.x-scenario/src/main/webapp/WEB-INF/web.xml @@ -20,7 +20,7 @@ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> - skywalking-spring-scheduled-scenario + skywalking-spring-scheduled-6.x-scenario spring-mvc diff --git a/test/plugin/scenarios/spring-scheduled-6.x-scenario/support-version.list b/test/plugin/scenarios/spring-scheduled-6.x-scenario/support-version.list new file mode 100644 index 0000000000..44322d6089 --- /dev/null +++ b/test/plugin/scenarios/spring-scheduled-6.x-scenario/support-version.list @@ -0,0 +1,18 @@ +# 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. + +6.0.19 +6.1.6 \ No newline at end of file From b608d74c158f01defb963c7d127f33b0cf509e4c Mon Sep 17 00:00:00 2001 From: gzlicanyi Date: Fri, 17 May 2024 13:43:51 +0800 Subject: [PATCH 014/114] Add a forceIgnoring mechanism to the agent kernel (#689) IgnoredTracerContext can propagate the unsampled flag into the following tracing context through the invalid snapshot. --- CHANGES.md | 1 + .../core/context/AbstractTracerContext.java | 6 ++ .../agent/core/context/ContextManager.java | 9 +- .../core/context/IgnoredTracerContext.java | 12 +++ .../agent/core/context/TracingContext.java | 8 ++ .../core/context/trace/AbstractSpan.java | 5 + .../context/trace/AbstractTracingSpan.java | 24 ++++- .../agent/core/context/trace/ExitSpan.java | 4 +- .../agent/core/context/trace/NoopSpan.java | 4 + .../core/context/ContinuedContextTest.java | 98 +++++++++++++++++++ .../v3/OnExceptionInterceptorTest.java | 3 +- .../rocketMQ/v3/OnSuccessInterceptorTest.java | 3 +- .../v4/OnExceptionInterceptorTest.java | 3 +- .../rocketMQ/v4/OnSuccessInterceptorTest.java | 3 +- .../core/context/MockContextSnapshot.java | 14 +++ .../CallableOrRunnableInterceptorTest.java | 20 ++-- 16 files changed, 202 insertions(+), 15 deletions(-) create mode 100644 apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/ContinuedContextTest.java diff --git a/CHANGES.md b/CHANGES.md index 0340de503d..66f717e538 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ Release Notes. * Fix typos in `URLParser`. * Add support for `Derby`/`Sybase`/`SQLite`/`DB2`/`OceanBase` jdbc url format in `URLParser`. * Optimize spring-plugins:scheduled-annotation-plugin compatibility about Spring 6.1.x support. +* Add a forceIgnoring mechanism in a CROSS_THREAD scenario. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java index a212e126e9..01d8ba99d2 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/AbstractTracerContext.java @@ -138,4 +138,10 @@ public interface AbstractTracerContext { * Get current primary endpoint name */ String getPrimaryEndpointName(); + + /** + * Change the current context to be in ignoring status. + */ + AbstractTracerContext forceIgnoring(); + } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java index c1ed28fd9d..fe90d979cf 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java @@ -163,7 +163,14 @@ public static void continued(ContextSnapshot snapshot) { throw new IllegalArgumentException("ContextSnapshot can't be null."); } if (!snapshot.isFromCurrent()) { - get().continued(snapshot); + // Invalid snapshot is only created by {@link IgnoredTracerContext#capture()}. + // When the snapshot is not valid, need to force ignoring the current tracing context. + if (snapshot.isValid()) { + get().continued(snapshot); + } else { + AbstractTracerContext context = get().forceIgnoring(); + CONTEXT.set(context); + } } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java index 67fabd3e0a..b91258ea6a 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java @@ -47,6 +47,13 @@ public IgnoredTracerContext() { this.profileStatusContext = ProfileStatusContext.createWithNone(); } + public IgnoredTracerContext(int stackDepth) { + this.stackDepth = stackDepth; + this.correlationContext = new CorrelationContext(); + this.extensionContext = new ExtensionContext(); + this.profileStatusContext = ProfileStatusContext.createWithNone(); + } + @Override public void inject(ContextCarrier carrier) { this.correlationContext.inject(carrier); @@ -134,6 +141,11 @@ public String getPrimaryEndpointName() { return null; } + @Override + public AbstractTracerContext forceIgnoring() { + return this; + } + public static class ListenerManager { private static List LISTENERS = new LinkedList<>(); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java index 305672bb2a..cffdbb2d38 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java @@ -419,6 +419,14 @@ public String getPrimaryEndpointName() { return primaryEndpoint.getName(); } + @Override + public AbstractTracerContext forceIgnoring() { + for (AbstractSpan span: activeSpanStack) { + span.forceIgnoring(); + } + return new IgnoredTracerContext(activeSpanStack.size()); + } + /** * Re-check current trace need profiling, encase third part plugin change the operation name. * diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java index 91a8c79432..9a1b6c93eb 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractSpan.java @@ -124,4 +124,9 @@ public interface AbstractSpan extends AsyncSpan { * Should skip analysis in the backend. */ void skipAnalysis(); + + /** + * Set to ignored status. + */ + void forceIgnoring(); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java index 83736bd5d8..6c682ca412 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java @@ -63,7 +63,8 @@ public abstract class AbstractTracingSpan implements AbstractSpan { private volatile boolean isAsyncStopped = false; /** - * The context to which the span belongs + * The context to which the span belongs. + * This should not be called when {@link #ignored} is true. */ protected final TracingContext owner; @@ -99,6 +100,11 @@ public abstract class AbstractTracingSpan implements AbstractSpan { */ protected boolean skipAnalysis; + /** + * The ignore flag of this span. + */ + protected boolean ignored; + protected AbstractTracingSpan(int spanId, int parentSpanId, String operationName, TracingContext owner) { this.operationName = operationName; this.spanId = spanId; @@ -318,7 +324,9 @@ public AbstractSpan prepareForAsync() { if (isInAsyncMode) { throw new RuntimeException("Prepare for async repeatedly. Span is already in async mode."); } - ContextManager.awaitFinishAsync(this); + if (!ignored) { + ContextManager.awaitFinishAsync(this); + } isInAsyncMode = true; return this; } @@ -332,13 +340,18 @@ public AbstractSpan asyncFinish() { throw new RuntimeException("Can not do async finish for the span repeatedly."); } this.endTime = System.currentTimeMillis(); - owner.asyncStop(this); + if (!ignored) { + owner.asyncStop(this); + } isAsyncStopped = true; return this; } @Override public boolean isProfiling() { + if (ignored) { + return false; + } return this.owner.profileStatus().isProfiling(); } @@ -346,4 +359,9 @@ public boolean isProfiling() { public void skipAnalysis() { this.skipAnalysis = true; } + + @Override + public void forceIgnoring() { + this.ignored = true; + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/ExitSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/ExitSpan.java index e61a8d1cab..18e391be4e 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/ExitSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/ExitSpan.java @@ -111,7 +111,9 @@ public String getPeer() { @Override public ExitSpan inject(final ContextCarrier carrier) { - this.owner.inject(this, carrier); + if (!ignored) { + this.owner.inject(this, carrier); + } return this; } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java index c67148abea..59dfb1a78a 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/NoopSpan.java @@ -123,6 +123,10 @@ public boolean isProfiling() { public void skipAnalysis() { } + @Override + public void forceIgnoring() { + } + @Override public AbstractSpan prepareForAsync() { return this; diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/ContinuedContextTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/ContinuedContextTest.java new file mode 100644 index 0000000000..55bfadada2 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/ContinuedContextTest.java @@ -0,0 +1,98 @@ +/* + * 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.agent.core.context; + +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.conf.Config; +import org.apache.skywalking.apm.agent.core.context.ids.NewDistributedTraceId; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.LocalSpan; +import org.apache.skywalking.apm.agent.core.context.trace.NoopSpan; +import org.apache.skywalking.apm.agent.core.profile.ProfileStatusContext; +import org.apache.skywalking.apm.agent.core.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.core.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.core.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.core.test.tools.TracingSegmentRunner; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.Assert; + +@RunWith(TracingSegmentRunner.class) +public class ContinuedContextTest { + + @SegmentStoragePoint + private SegmentStorage tracingData; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + + @BeforeClass + public static void beforeClass() { + Config.Agent.KEEP_TRACING = true; + } + + @AfterClass + public static void afterClass() { + Config.Agent.KEEP_TRACING = false; + ServiceManager.INSTANCE.shutdown(); + } + + @Test + public void testContinued() { + + NewDistributedTraceId distributedTraceId = new NewDistributedTraceId(); + ContextSnapshot snapshot = new ContextSnapshot( + "1, 2, 3", + 1, + distributedTraceId, + "/for-test-continued", + new CorrelationContext(), + new ExtensionContext(), + ProfileStatusContext.createWithNone() + ); + + AbstractSpan span = ContextManager.createLocalSpan("test-span"); + ContextManager.continued(snapshot); + + Assert.assertEquals(distributedTraceId.getId(), ContextManager.getGlobalTraceId()); + ContextManager.stopSpan(); + } + + @Test + public void testContinuedWithIgnoredSnapshot() { + + ContextSnapshot snapshot = + new ContextSnapshot(null, -1, null, null, new CorrelationContext(), new ExtensionContext(), ProfileStatusContext.createWithNone()); + + AbstractSpan span = ContextManager.createLocalSpan("test-span"); + ContextManager.continued(snapshot); + + Assert.assertTrue(span instanceof LocalSpan); + + AbstractSpan span2 = ContextManager.createLocalSpan("test-span2"); + Assert.assertTrue(span2 instanceof NoopSpan); + + ContextManager.stopSpan(); + ContextManager.stopSpan(); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v3/OnExceptionInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v3/OnExceptionInterceptorTest.java index 59bf780148..6b5ba982f8 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v3/OnExceptionInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v3/OnExceptionInterceptorTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.when; import java.util.List; import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.MockContextSnapshot; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; @@ -55,7 +56,6 @@ public class OnExceptionInterceptorTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); - @Mock private ContextSnapshot contextSnapshot; private SendCallBackEnhanceInfo enhanceInfo; @@ -65,6 +65,7 @@ public class OnExceptionInterceptorTest { @Before public void setUp() { exceptionInterceptor = new OnExceptionInterceptor(); + contextSnapshot = MockContextSnapshot.INSTANCE.mockContextSnapshot(); enhanceInfo = new SendCallBackEnhanceInfo("test", contextSnapshot); when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(enhanceInfo); diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v3/OnSuccessInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v3/OnSuccessInterceptorTest.java index 0927f8a793..77c69a01e6 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v3/OnSuccessInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v3/OnSuccessInterceptorTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.when; import java.util.List; import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.MockContextSnapshot; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; @@ -57,7 +58,6 @@ public class OnSuccessInterceptorTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); - @Mock private ContextSnapshot contextSnapshot; @Mock private SendResult sendResult; @@ -70,6 +70,7 @@ public class OnSuccessInterceptorTest { @Before public void setUp() { successInterceptor = new OnSuccessInterceptor(); + contextSnapshot = MockContextSnapshot.INSTANCE.mockContextSnapshot(); enhanceInfo = new SendCallBackEnhanceInfo("test", contextSnapshot); when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(enhanceInfo); diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/OnExceptionInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/OnExceptionInterceptorTest.java index 169c3b59bb..3bc9436b1d 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/OnExceptionInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/OnExceptionInterceptorTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.when; import java.util.List; import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.MockContextSnapshot; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; @@ -55,7 +56,6 @@ public class OnExceptionInterceptorTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); - @Mock private ContextSnapshot contextSnapshot; private SendCallBackEnhanceInfo enhanceInfo; @@ -69,6 +69,7 @@ public void setUp() { @Test public void testOnException() throws Throwable { + contextSnapshot = MockContextSnapshot.INSTANCE.mockContextSnapshot(); enhanceInfo = new SendCallBackEnhanceInfo("test", contextSnapshot); when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(enhanceInfo); diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/OnSuccessInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/OnSuccessInterceptorTest.java index d432daafd8..40c718d9b3 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/OnSuccessInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/rocketMQ/v4/OnSuccessInterceptorTest.java @@ -25,6 +25,7 @@ import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.client.producer.SendStatus; import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.MockContextSnapshot; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; @@ -57,7 +58,6 @@ public class OnSuccessInterceptorTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); - @Mock private ContextSnapshot contextSnapshot; @Mock private SendResult sendResult; @@ -70,6 +70,7 @@ public class OnSuccessInterceptorTest { @Before public void setUp() { successInterceptor = new OnSuccessInterceptor(); + contextSnapshot = MockContextSnapshot.INSTANCE.mockContextSnapshot(); enhanceInfo = new SendCallBackEnhanceInfo("test", contextSnapshot); when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(enhanceInfo); diff --git a/apm-sniffer/apm-test-tools/src/main/java/org/apache/skywalking/apm/agent/core/context/MockContextSnapshot.java b/apm-sniffer/apm-test-tools/src/main/java/org/apache/skywalking/apm/agent/core/context/MockContextSnapshot.java index 505a4924a9..c6d5f91fcc 100644 --- a/apm-sniffer/apm-test-tools/src/main/java/org/apache/skywalking/apm/agent/core/context/MockContextSnapshot.java +++ b/apm-sniffer/apm-test-tools/src/main/java/org/apache/skywalking/apm/agent/core/context/MockContextSnapshot.java @@ -26,6 +26,8 @@ public enum MockContextSnapshot { private ContextSnapshot contextSnapshot; + private ContextSnapshot ignoreContextSnapshot; + MockContextSnapshot() { contextSnapshot = new ContextSnapshot( "1, 2, 3", @@ -36,9 +38,21 @@ public enum MockContextSnapshot { new ExtensionContext(), ProfileStatusContext.createWithNone() ); + ignoreContextSnapshot = new ContextSnapshot( + null, + -1, + null, + null, + new CorrelationContext(), + new ExtensionContext(), + ProfileStatusContext.createWithNone()); } public ContextSnapshot mockContextSnapshot() { return contextSnapshot; } + + public ContextSnapshot mockIgnoreContextSnapshot() { + return ignoreContextSnapshot; + } } diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/CallableOrRunnableInterceptorTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/CallableOrRunnableInterceptorTest.java index 45e00baa73..3aacc88c67 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/CallableOrRunnableInterceptorTest.java +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/CallableOrRunnableInterceptorTest.java @@ -22,7 +22,7 @@ import java.lang.reflect.Method; import java.util.List; import java.util.concurrent.Callable; -import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.MockContextSnapshot; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; @@ -36,7 +36,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -69,9 +68,6 @@ public void setSkyWalkingDynamicField(Object value) { } }; - @Mock - private ContextSnapshot contextSnapshot; - private Object[] arguments; private Method callMethod; @@ -100,7 +96,7 @@ public void testOnConstructor() { @Test public void testCall() throws Throwable { - enhancedInstance.setSkyWalkingDynamicField(contextSnapshot); + enhancedInstance.setSkyWalkingDynamicField(MockContextSnapshot.INSTANCE.mockContextSnapshot()); callableCallInterceptor.beforeMethod(enhancedInstance, callMethod, arguments, null, null); callableCallInterceptor.afterMethod(enhancedInstance, callMethod, arguments, null, "result"); @@ -111,4 +107,16 @@ public void testCall() throws Throwable { } + @Test + public void testCallWithIgnoreSnapshot() throws Throwable { + + enhancedInstance.setSkyWalkingDynamicField(MockContextSnapshot.INSTANCE.mockIgnoreContextSnapshot()); + callableCallInterceptor.beforeMethod(enhancedInstance, callMethod, arguments, null, null); + callableCallInterceptor.afterMethod(enhancedInstance, callMethod, arguments, null, "result"); + + assertThat(segmentStorage.getTraceSegments().size(), is(0)); + assertThat(segmentStorage.getIgnoredTracerContexts().size(), is(1)); + + } + } From ffbd90c3d371259d44cca038f3810a99c9de7594 Mon Sep 17 00:00:00 2001 From: Chen Ziyan Date: Wed, 22 May 2024 14:28:58 +0800 Subject: [PATCH 015/114] Fix bugs in Redisson plugin (#693) --- CHANGES.md | 3 ++ .../redisson-3.x-plugin/pom.xml | 2 +- .../v3/ConnectionManagerInterceptor.java | 43 ++++++++++++++----- .../v3/RedisConnectionMethodInterceptor.java | 19 +++++++- .../redisson/v3/RedissonPluginConfig.java | 8 ++++ .../java-agent/Supported-list.md | 2 +- .../redisson-scenario/support-version.list | 7 +++ 7 files changed, 70 insertions(+), 14 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 66f717e538..b6b6724e40 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,9 @@ Release Notes. * Add support for `Derby`/`Sybase`/`SQLite`/`DB2`/`OceanBase` jdbc url format in `URLParser`. * Optimize spring-plugins:scheduled-annotation-plugin compatibility about Spring 6.1.x support. * Add a forceIgnoring mechanism in a CROSS_THREAD scenario. +* Fix NPE in Redisson plugin since Redisson 3.20.0. +* Support for showing batch command details and ignoring PING commands in Redisson plugin. +* Fix peer value of Master-Slave mode in Redisson plugin. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml index 2e0d14219d..19f79cbc3e 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml @@ -31,7 +31,7 @@ redisson-3.x-plugin http://maven.apache.org - 3.6.0 + 3.20.0 diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/ConnectionManagerInterceptor.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/ConnectionManagerInterceptor.java index d4b352deea..8cdb79b9ff 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/ConnectionManagerInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/ConnectionManagerInterceptor.java @@ -18,6 +18,7 @@ package org.apache.skywalking.apm.plugin.redisson.v3; +import java.util.Objects; import org.apache.skywalking.apm.agent.core.context.util.PeerFormat; import org.apache.skywalking.apm.agent.core.logging.api.ILog; import org.apache.skywalking.apm.agent.core.logging.api.LogManager; @@ -26,11 +27,12 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.plugin.redisson.v3.util.ClassUtil; import org.redisson.config.Config; -import org.redisson.connection.ConnectionManager; import java.lang.reflect.Method; import java.net.URI; import java.util.Collection; +import org.redisson.connection.MasterSlaveConnectionManager; +import org.redisson.connection.ServiceManager; public class ConnectionManagerInterceptor implements InstanceMethodsAroundInterceptor { @@ -45,14 +47,19 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { try { - ConnectionManager connectionManager = (ConnectionManager) objInst; - Config config = connectionManager.getCfg(); - - Object singleServerConfig = ClassUtil.getObjectField(config, "singleServerConfig"); - Object sentinelServersConfig = ClassUtil.getObjectField(config, "sentinelServersConfig"); - Object masterSlaveServersConfig = ClassUtil.getObjectField(config, "masterSlaveServersConfig"); - Object clusterServersConfig = ClassUtil.getObjectField(config, "clusterServersConfig"); - Object replicatedServersConfig = ClassUtil.getObjectField(config, "replicatedServersConfig"); + Config config = getConfig(objInst); + Object singleServerConfig = null; + Object sentinelServersConfig = null; + Object masterSlaveServersConfig = null; + Object clusterServersConfig = null; + Object replicatedServersConfig = null; + if (Objects.nonNull(config)) { + singleServerConfig = ClassUtil.getObjectField(config, "singleServerConfig"); + sentinelServersConfig = ClassUtil.getObjectField(config, "sentinelServersConfig"); + masterSlaveServersConfig = ClassUtil.getObjectField(config, "masterSlaveServersConfig"); + clusterServersConfig = ClassUtil.getObjectField(config, "clusterServersConfig"); + replicatedServersConfig = ClassUtil.getObjectField(config, "replicatedServersConfig"); + } StringBuilder peer = new StringBuilder(); EnhancedInstance retInst = (EnhancedInstance) ret; @@ -70,7 +77,7 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA } if (masterSlaveServersConfig != null) { Object masterAddress = ClassUtil.getObjectField(masterSlaveServersConfig, "masterAddress"); - peer.append(getPeer(masterAddress)); + peer.append(getPeer(masterAddress)).append(";"); appendAddresses(peer, (Collection) ClassUtil.getObjectField(masterSlaveServersConfig, "slaveAddresses")); retInst.setSkyWalkingDynamicField(PeerFormat.shorten(peer.toString())); return ret; @@ -118,6 +125,22 @@ static String getPeer(Object obj) { } } + private Config getConfig(EnhancedInstance objInst) { + Config config = null; + MasterSlaveConnectionManager connectionManager = (MasterSlaveConnectionManager) objInst; + try { + config = (Config) ClassUtil.getObjectField(connectionManager, "cfg"); + } catch (NoSuchFieldException | IllegalAccessException ignore) { + try { + ServiceManager serviceManager = (ServiceManager) ClassUtil.getObjectField( + connectionManager, "serviceManager"); + config = serviceManager.getCfg(); + } catch (NoSuchFieldException | IllegalAccessException ignore2) { + } + } + return config; + } + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java index 60956c7a64..f660ca1a15 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java @@ -19,6 +19,7 @@ package org.apache.skywalking.apm.plugin.redisson.v3; import io.netty.channel.Channel; +import java.util.stream.Collectors; import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; @@ -66,11 +67,18 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr if (allArguments[0] instanceof CommandsData) { operationName = operationName + "BATCH_EXECUTE"; command = "BATCH_EXECUTE"; + if (RedissonPluginConfig.Plugin.Redisson.SHOW_BATCH_COMMANDS) { + command += ":" + showBatchCommands((CommandsData) allArguments[0]); + } } else if (allArguments[0] instanceof CommandData) { CommandData commandData = (CommandData) allArguments[0]; command = commandData.getCommand().getName(); - operationName = operationName + command; - arguments = commandData.getParams(); + if ("PING".equals(command) && !RedissonPluginConfig.Plugin.Redisson.SHOW_PING_COMMAND) { + return; + } else { + operationName = operationName + command; + arguments = commandData.getParams(); + } } AbstractSpan span = ContextManager.createExitSpan(operationName, peer); @@ -143,4 +151,11 @@ private Optional parseOperation(String cmd) { } return Optional.empty(); } + + private String showBatchCommands(CommandsData commandsData) { + return commandsData.getCommands() + .stream() + .map(data -> data.getCommand().getName()) + .collect(Collectors.joining(";")); + } } diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java index 52dedcb10a..aeb0a5f270 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java @@ -40,6 +40,14 @@ public static class Redisson { * Set a negative number to save specified length of parameter string to the tag. */ public static int REDIS_PARAMETER_MAX_LENGTH = 128; + /** + * If set to true, the PING command would be collected. + */ + public static boolean SHOW_PING_COMMAND = false; + /** + * If set to true, the detail of the Redis batch commands would be collected. + */ + public static boolean SHOW_BATCH_COMMANDS = false; /** * Operation represent a cache span is "write" or "read" action , and "op"(operation) is tagged with key "cache.op" usually diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 1fa2672282..12b712bbf4 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -87,7 +87,7 @@ metrics based on the tracing data. * [aerospike](https://github.com/aerospike/aerospike-client-java) 3.x -> 6.x * Redis * [Jedis](https://github.com/xetorthio/jedis) 2.x-4.x - * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 3.5.2+ + * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 3.5.0 -> 3.30.0 * [Lettuce](https://github.com/lettuce-io/lettuce-core) 5.x * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14, 3.4.0-3.12.7, 4.0.0-4.1.0 * Memcached Client diff --git a/test/plugin/scenarios/redisson-scenario/support-version.list b/test/plugin/scenarios/redisson-scenario/support-version.list index 78009656c1..aa0a5594df 100644 --- a/test/plugin/scenarios/redisson-scenario/support-version.list +++ b/test/plugin/scenarios/redisson-scenario/support-version.list @@ -14,6 +14,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# 3.5.0-3.12.4, 3.26.1-3.30.0 have been tested, and 3.12.5-3.26.0 are also supported but not included in the test +3.30.0 +3.29.0 +3.28.0 +3.27.2 +3.26.1 +3.12.4 3.11.5 3.10.7 3.9.1 From f736b371d3c92793a25ffa15f6c719c5fe624b82 Mon Sep 17 00:00:00 2001 From: Chen Ziyan Date: Tue, 28 May 2024 00:18:56 +0800 Subject: [PATCH 016/114] Support for tracing the callbacks of async methods in elastiicsearch-6.x/7.x-plugin (#694) --- CHANGES.md | 1 + .../define/IndicesClientInstrumentation.java | 8 +- .../RestHighLevelClientInstrumentation.java | 16 +- .../v6/interceptor/Constants.java | 3 + ...ndicesClientAnalyzeMethodsInterceptor.java | 6 + ...IndicesClientCreateMethodsInterceptor.java | 6 + ...IndicesClientDeleteMethodsInterceptor.java | 6 + ...ndicesClientRefreshMethodsInterceptor.java | 6 + ...elClientClearScrollMethodsInterceptor.java | 6 + ...ClientDeleteByQueryMethodsInterceptor.java | 6 + ...tHighLevelClientGetMethodsInterceptor.java | 6 + ...ighLevelClientIndexMethodsInterceptor.java | 6 + ...ghLevelClientSearchMethodsInterceptor.java | 6 + ...lClientSearchScrollMethodsInterceptor.java | 6 + ...lientSearchTemplateMethodsInterceptor.java | 6 + ...ghLevelClientUpdateMethodsInterceptor.java | 6 + .../v6/support/ActionListenerAdapter.java | 92 +++ .../elasticsearch/v6/support/AdapterUtil.java | 40 ++ .../v6/support/RestClientCache.java | 62 ++ .../plugin/elasticsearch/v7/Constants.java | 4 + .../define/IndicesClientInstrumentation.java | 8 +- ...ndicesClientAnalyzeMethodsInterceptor.java | 6 + ...IndicesClientCreateMethodsInterceptor.java | 7 + ...IndicesClientDeleteMethodsInterceptor.java | 7 + ...ndicesClientRefreshMethodsInterceptor.java | 7 + .../v7/support/ActionListenerAdapter.java | 92 +++ .../elasticsearch/v7/support/AdapterUtil.java | 40 ++ .../v7/support/RestClientCache.java | 62 ++ .../java-agent/Supported-list.md | 2 +- .../config/expectedData.yaml | 631 ++++++++++++++---- .../RestHighLevelClientCase.java | 220 ++++++ .../support-version.list | 3 +- 32 files changed, 1223 insertions(+), 160 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/ActionListenerAdapter.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/AdapterUtil.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/RestClientCache.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/ActionListenerAdapter.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/AdapterUtil.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/RestClientCache.java diff --git a/CHANGES.md b/CHANGES.md index b6b6724e40..321c775094 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ Release Notes. * Fix NPE in Redisson plugin since Redisson 3.20.0. * Support for showing batch command details and ignoring PING commands in Redisson plugin. * Fix peer value of Master-Slave mode in Redisson plugin. +* Support for tracing the callbacks of asynchronous methods in elasticsearch-6.x-plugin/elasticsearch-7.x-plugin. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/IndicesClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/IndicesClientInstrumentation.java index 0031efb96a..75b494b249 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/IndicesClientInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/IndicesClientInstrumentation.java @@ -68,7 +68,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -85,7 +85,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -102,7 +102,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -119,7 +119,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } } }; diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/RestHighLevelClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/RestHighLevelClientInstrumentation.java index 8185926181..68b434740a 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/RestHighLevelClientInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/define/RestHighLevelClientInstrumentation.java @@ -86,7 +86,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -102,7 +102,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -118,7 +118,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -134,7 +134,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -182,7 +182,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -198,7 +198,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -214,7 +214,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -230,7 +230,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } } }; diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/Constants.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/Constants.java index bf9322ed7f..6d61006e9f 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/Constants.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/Constants.java @@ -79,4 +79,7 @@ public class Constants { public static final AbstractTag ES_TOOK_MILLIS = Tags.ofKey("es.took_millis"); public static final AbstractTag ES_TOTAL_HITS = Tags.ofKey("es.total_hits"); public static final AbstractTag ES_INGEST_TOOK_MILLIS = Tags.ofKey("es.ingest_took_millis"); + + public static final String ON_RESPONSE_SUFFIX = "/onResponse"; + public static final String ON_FAILURE_SUFFIX = "/onFailure"; } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientAnalyzeMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientAnalyzeMethodsInterceptor.java index 8ab77d4e86..6d8338e497 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientAnalyzeMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientAnalyzeMethodsInterceptor.java @@ -30,6 +30,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest; import java.lang.reflect.Method; @@ -58,6 +60,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Tags.DB_STATEMENT.set(span, analyzeRequest.text()[0]); } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.ANALYZE_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientCreateMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientCreateMethodsInterceptor.java index ae17f85d75..b1b95481ec 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientCreateMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientCreateMethodsInterceptor.java @@ -28,6 +28,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.client.indices.CreateIndexRequest; import static org.apache.skywalking.apm.plugin.elasticsearch.v6.ElasticsearchPluginConfig.Plugin.Elasticsearch.TRACE_DSL; @@ -52,6 +54,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Tags.DB_STATEMENT.set(span, createIndexRequest.mappings().utf8ToString()); } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.CREATE_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientDeleteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientDeleteMethodsInterceptor.java index 454afa08b6..68c7377dfe 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientDeleteMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientDeleteMethodsInterceptor.java @@ -29,6 +29,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import static org.apache.skywalking.apm.plugin.elasticsearch.v6.interceptor.Constants.DB_TYPE; @@ -48,6 +50,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Tags.DB_TYPE.set(span, DB_TYPE); Tags.DB_INSTANCE.set(span, Arrays.asList(deleteIndexRequest.indices()).toString()); SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.DELETE_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientRefreshMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientRefreshMethodsInterceptor.java index 9e3cb6fc17..cb9dfbb384 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientRefreshMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/IndicesClientRefreshMethodsInterceptor.java @@ -27,6 +27,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; import java.lang.reflect.Method; @@ -48,6 +50,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Tags.DB_TYPE.set(span, DB_TYPE); Tags.DB_INSTANCE.set(span, buildIndicesString(request.indices())); SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.REFRESH_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientClearScrollMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientClearScrollMethodsInterceptor.java index d1099f8ebc..2a65908af4 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientClearScrollMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientClearScrollMethodsInterceptor.java @@ -27,6 +27,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.search.ClearScrollRequest; import java.lang.reflect.Method; @@ -52,6 +54,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.CLEAR_SCROLL_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientDeleteByQueryMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientDeleteByQueryMethodsInterceptor.java index 654c7df7b9..aba54fe54e 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientDeleteByQueryMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientDeleteByQueryMethodsInterceptor.java @@ -27,6 +27,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.index.reindex.DeleteByQueryRequest; import java.lang.reflect.Method; @@ -58,6 +60,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.DELETE_BY_QUERY_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientGetMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientGetMethodsInterceptor.java index 171bd29802..32c9c24c73 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientGetMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientGetMethodsInterceptor.java @@ -28,6 +28,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.get.GetRequest; import static org.apache.skywalking.apm.plugin.elasticsearch.v6.ElasticsearchPluginConfig.Plugin.Elasticsearch.TRACE_DSL; @@ -51,6 +53,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.GET_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientIndexMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientIndexMethodsInterceptor.java index c2075207d6..0e7744f7c4 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientIndexMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientIndexMethodsInterceptor.java @@ -28,6 +28,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.index.IndexRequest; import static org.apache.skywalking.apm.plugin.elasticsearch.v6.ElasticsearchPluginConfig.Plugin.Elasticsearch.TRACE_DSL; @@ -51,6 +53,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.INDEX_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchMethodsInterceptor.java index cc709d6273..fb941490ba 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchMethodsInterceptor.java @@ -29,6 +29,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.search.SearchRequest; import static org.apache.skywalking.apm.plugin.elasticsearch.v6.ElasticsearchPluginConfig.Plugin.Elasticsearch.TRACE_DSL; @@ -52,6 +54,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.SEARCH_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchScrollMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchScrollMethodsInterceptor.java index 64d503618e..1b4be55ea6 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchScrollMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchScrollMethodsInterceptor.java @@ -27,6 +27,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.search.SearchScrollRequest; import java.lang.reflect.Method; @@ -51,6 +53,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.SEARCH_SCROLL_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchTemplateMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchTemplateMethodsInterceptor.java index f57a652b15..b4d945fdb2 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchTemplateMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientSearchTemplateMethodsInterceptor.java @@ -27,6 +27,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.script.mustache.SearchTemplateRequest; import java.lang.reflect.Method; @@ -55,6 +57,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.SEARCH_TEMPLATE_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientUpdateMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientUpdateMethodsInterceptor.java index b3a34e1aa1..7d76894ade 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientUpdateMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/interceptor/RestHighLevelClientUpdateMethodsInterceptor.java @@ -28,6 +28,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.update.UpdateRequest; import static org.apache.skywalking.apm.plugin.elasticsearch.v6.ElasticsearchPluginConfig.Plugin.Elasticsearch.TRACE_DSL; @@ -51,6 +53,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.UPDATE_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/ActionListenerAdapter.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/ActionListenerAdapter.java new file mode 100644 index 0000000000..8bcb7d23ea --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/ActionListenerAdapter.java @@ -0,0 +1,92 @@ +/* + * 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.elasticsearch.v6.support; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.elasticsearch.v6.interceptor.Constants; +import org.elasticsearch.action.ActionListener; + +import static org.apache.skywalking.apm.plugin.elasticsearch.v6.interceptor.Constants.DB_TYPE; + +public class ActionListenerAdapter implements ActionListener, EnhancedInstance { + + private final RestClientCache restClientCache; + + public ActionListenerAdapter(RestClientCache restClientCache) { + this.restClientCache = restClientCache; + } + + @Override + public void onResponse(final T o) { + try { + if (restClientCache.getContextSnapshot() != null) { + continueContext(Constants.ON_RESPONSE_SUFFIX); + } + if (restClientCache.getActionListener() != null) { + restClientCache.getActionListener().onResponse(o); + } + } catch (Throwable t) { + ContextManager.activeSpan().log(t); + throw t; + } finally { + restClientCache.setContextSnapshot(null); + ContextManager.stopSpan(); + } + } + + @Override + public void onFailure(final Exception e) { + try { + if (restClientCache.getContextSnapshot() != null) { + continueContext(Constants.ON_FAILURE_SUFFIX); + } + if (restClientCache.getActionListener() != null) { + restClientCache.getActionListener().onFailure(e); + } + } catch (Throwable t) { + ContextManager.activeSpan().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } + + @Override + public Object getSkyWalkingDynamicField() { + return restClientCache; + } + + @Override + public void setSkyWalkingDynamicField(final Object enhanceInfo) { + + } + + private void continueContext(String action) { + AbstractSpan activeSpan = ContextManager.createLocalSpan(restClientCache.getOperationName() + action); + activeSpan.setComponent(ComponentsDefine.REST_HIGH_LEVEL_CLIENT); + Tags.DB_TYPE.set(activeSpan, DB_TYPE); + SpanLayer.asDB(activeSpan); + ContextManager.continued(restClientCache.getContextSnapshot()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/AdapterUtil.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/AdapterUtil.java new file mode 100644 index 0000000000..f275fc98c8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/AdapterUtil.java @@ -0,0 +1,40 @@ +/* + * 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.elasticsearch.v6.support; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.elasticsearch.action.ActionListener; + +public class AdapterUtil { + + public static ActionListener wrapActionListener(RestClientEnhanceInfo restClientEnhanceInfo, + String operation, + ActionListener listener) { + ContextSnapshot capture = ContextManager.capture(); + capture.getExtensionContext().setSendingTimestamp(System.currentTimeMillis()); + RestClientCache cache = new RestClientCache(); + cache.setEnhanceInfo(restClientEnhanceInfo); + cache.setContextSnapshot(capture); + cache.setOperationName(operation); + cache.setActionListener(listener); + return new ActionListenerAdapter(cache); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/RestClientCache.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/RestClientCache.java new file mode 100644 index 0000000000..2c81df0024 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v6/support/RestClientCache.java @@ -0,0 +1,62 @@ +/* + * 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.elasticsearch.v6.support; + +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.elasticsearch.action.ActionListener; + +public class RestClientCache { + private RestClientEnhanceInfo enhanceInfo; + private ActionListener actionListener; + private ContextSnapshot contextSnapshot; + private String operationName; + + public ContextSnapshot getContextSnapshot() { + return contextSnapshot; + } + + public void setContextSnapshot(final ContextSnapshot contextSnapshot) { + this.contextSnapshot = contextSnapshot; + } + + public String getOperationName() { + return operationName; + } + + public void setOperationName(final String operationName) { + this.operationName = operationName; + } + + public ActionListener getActionListener() { + return actionListener; + } + + public void setActionListener(final ActionListener actionListener) { + this.actionListener = actionListener; + } + + public RestClientEnhanceInfo getEnhanceInfo() { + return enhanceInfo; + } + + public void setEnhanceInfo(final RestClientEnhanceInfo enhanceInfo) { + this.enhanceInfo = enhanceInfo; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/Constants.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/Constants.java index b7408b7c94..f9f72eb21d 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/Constants.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/Constants.java @@ -48,4 +48,8 @@ public class Constants { public static final AbstractTag ES_TOOK_MILLIS = Tags.ofKey("es.took_millis"); public static final AbstractTag ES_TOTAL_HITS = Tags.ofKey("es.total_hits"); public static final AbstractTag ES_INGEST_TOOK_MILLIS = Tags.ofKey("es.ingest_took_millis"); + + public static final String ON_RESPONSE_SUFFIX = "/onResponse"; + public static final String ON_FAILURE_SUFFIX = "/onFailure"; + } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/define/IndicesClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/define/IndicesClientInstrumentation.java index 158a3b1ce6..5ce24546ee 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/define/IndicesClientInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/define/IndicesClientInstrumentation.java @@ -62,7 +62,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -79,7 +79,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -96,7 +96,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } }, new InstanceMethodsInterceptPoint() { @@ -113,7 +113,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } } }; diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientAnalyzeMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientAnalyzeMethodsInterceptor.java index 15d3992066..3a1ff1e7f1 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientAnalyzeMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientAnalyzeMethodsInterceptor.java @@ -31,6 +31,8 @@ import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; import org.apache.skywalking.apm.plugin.elasticsearch.v7.Constants; +import org.apache.skywalking.apm.plugin.elasticsearch.v7.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.client.indices.AnalyzeRequest; import java.lang.reflect.Method; @@ -59,6 +61,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Tags.DB_STATEMENT.set(span, analyzeRequest.text()[0]); } SpanLayer.asDB(span); + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.ANALYZE_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientCreateMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientCreateMethodsInterceptor.java index e4ef7379fa..56b2af778a 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientCreateMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientCreateMethodsInterceptor.java @@ -28,6 +28,8 @@ import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; import org.apache.skywalking.apm.plugin.elasticsearch.v7.Constants; +import org.apache.skywalking.apm.plugin.elasticsearch.v7.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.client.indices.CreateIndexRequest; import java.lang.reflect.Method; @@ -49,6 +51,11 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Tags.DB_TYPE.set(span, DB_TYPE); Tags.DB_INSTANCE.set(span, createIndexRequest.index()); SpanLayer.asDB(span); + + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.CREATE_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientDeleteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientDeleteMethodsInterceptor.java index 37ee7658fd..e327688d91 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientDeleteMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientDeleteMethodsInterceptor.java @@ -28,6 +28,8 @@ import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; import org.apache.skywalking.apm.plugin.elasticsearch.v7.Constants; +import org.apache.skywalking.apm.plugin.elasticsearch.v7.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import java.lang.reflect.Method; @@ -50,6 +52,11 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Tags.DB_TYPE.set(span, DB_TYPE); Tags.DB_INSTANCE.set(span, Arrays.asList(deleteIndexRequest.indices()).toString()); SpanLayer.asDB(span); + + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.DELETE_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientRefreshMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientRefreshMethodsInterceptor.java index 8602be4272..95886ed82b 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientRefreshMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/interceptor/IndicesClientRefreshMethodsInterceptor.java @@ -28,6 +28,8 @@ import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; import org.apache.skywalking.apm.plugin.elasticsearch.v7.Constants; +import org.apache.skywalking.apm.plugin.elasticsearch.v7.support.AdapterUtil; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; import java.lang.reflect.Method; @@ -49,6 +51,11 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Tags.DB_TYPE.set(span, DB_TYPE); Tags.DB_INSTANCE.set(span, buildIndicesString(request.indices())); SpanLayer.asDB(span); + + if (allArguments.length > 2 && allArguments[2] != null && allArguments[2] instanceof ActionListener) { + allArguments[2] = AdapterUtil.wrapActionListener(restClientEnhanceInfo, Constants.REFRESH_OPERATOR_NAME, + (ActionListener) allArguments[2]); + } } } diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/ActionListenerAdapter.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/ActionListenerAdapter.java new file mode 100644 index 0000000000..f99178412b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/ActionListenerAdapter.java @@ -0,0 +1,92 @@ +/* + * 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.elasticsearch.v7.support; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.elasticsearch.v7.Constants; +import org.elasticsearch.action.ActionListener; + +import static org.apache.skywalking.apm.plugin.elasticsearch.v7.Constants.DB_TYPE; + +public class ActionListenerAdapter implements ActionListener, EnhancedInstance { + + private final RestClientCache restClientCache; + + public ActionListenerAdapter(RestClientCache restClientCache) { + this.restClientCache = restClientCache; + } + + @Override + public void onResponse(final T o) { + try { + if (restClientCache.getContextSnapshot() != null) { + continueContext(Constants.ON_RESPONSE_SUFFIX); + } + if (restClientCache.getActionListener() != null) { + restClientCache.getActionListener().onResponse(o); + } + } catch (Throwable t) { + ContextManager.activeSpan().log(t); + throw t; + } finally { + restClientCache.setContextSnapshot(null); + ContextManager.stopSpan(); + } + } + + @Override + public void onFailure(final Exception e) { + try { + if (restClientCache.getContextSnapshot() != null) { + continueContext(Constants.ON_FAILURE_SUFFIX); + } + if (restClientCache.getActionListener() != null) { + restClientCache.getActionListener().onFailure(e); + } + } catch (Throwable t) { + ContextManager.activeSpan().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } + + @Override + public Object getSkyWalkingDynamicField() { + return restClientCache; + } + + @Override + public void setSkyWalkingDynamicField(final Object enhanceInfo) { + + } + + private void continueContext(String action) { + AbstractSpan activeSpan = ContextManager.createLocalSpan(restClientCache.getOperationName() + action); + activeSpan.setComponent(ComponentsDefine.REST_HIGH_LEVEL_CLIENT); + Tags.DB_TYPE.set(activeSpan, DB_TYPE); + SpanLayer.asDB(activeSpan); + ContextManager.continued(restClientCache.getContextSnapshot()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/AdapterUtil.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/AdapterUtil.java new file mode 100644 index 0000000000..093b6c92ea --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/AdapterUtil.java @@ -0,0 +1,40 @@ +/* + * 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.elasticsearch.v7.support; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.elasticsearch.action.ActionListener; + +public class AdapterUtil { + + public static ActionListener wrapActionListener(RestClientEnhanceInfo restClientEnhanceInfo, + String operation, + ActionListener listener) { + ContextSnapshot capture = ContextManager.capture(); + capture.getExtensionContext().setSendingTimestamp(System.currentTimeMillis()); + RestClientCache cache = new RestClientCache(); + cache.setEnhanceInfo(restClientEnhanceInfo); + cache.setContextSnapshot(capture); + cache.setOperationName(operation); + cache.setActionListener(listener); + return new ActionListenerAdapter(cache); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/RestClientCache.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/RestClientCache.java new file mode 100644 index 0000000000..18f895578a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/v7/support/RestClientCache.java @@ -0,0 +1,62 @@ +/* + * 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.elasticsearch.v7.support; + +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.plugin.elasticsearch.common.RestClientEnhanceInfo; +import org.elasticsearch.action.ActionListener; + +public class RestClientCache { + private RestClientEnhanceInfo enhanceInfo; + private ActionListener actionListener; + private ContextSnapshot contextSnapshot; + private String operationName; + + public ContextSnapshot getContextSnapshot() { + return contextSnapshot; + } + + public void setContextSnapshot(final ContextSnapshot contextSnapshot) { + this.contextSnapshot = contextSnapshot; + } + + public String getOperationName() { + return operationName; + } + + public void setOperationName(final String operationName) { + this.operationName = operationName; + } + + public ActionListener getActionListener() { + return actionListener; + } + + public void setActionListener(final ActionListener actionListener) { + this.actionListener = actionListener; + } + + public RestClientEnhanceInfo getEnhanceInfo() { + return enhanceInfo; + } + + public void setEnhanceInfo(final RestClientEnhanceInfo enhanceInfo) { + this.enhanceInfo = enhanceInfo; + } +} diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 12b712bbf4..42a9c67539 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -98,7 +98,7 @@ metrics based on the tracing data. * [transport-client](https://github.com/elastic/elasticsearch/tree/v6.2.3/client/transport) 6.2.3-6.8.4 * [transport-client](https://github.com/elastic/elasticsearch/tree/7.0/client/transport) 7.0.0-7.5.2 * [rest-high-level-client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.7/index.html) 6.7.1-6.8.4 - * [rest-high-level-client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.0/java-rest-high.html) 7.0.0-7.5.2 + * [rest-high-level-client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.0/java-rest-high.html) 7.x * [Solr](https://github.com/apache/solr/) * [SolrJ](https://github.com/apache/solr/tree/main/solr/solrj) 7.x * [Cassandra](https://github.com/apache/cassandra) 3.x diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/elasticsearch-7.x-scenario/config/expectedData.yaml index af47b1b27e..33f33e7573 100644 --- a/test/plugin/scenarios/elasticsearch-7.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/config/expectedData.yaml @@ -15,7 +15,7 @@ # limitations under the License. segmentItems: - serviceName: elasticsearch-7.x-scenario - segmentSize: ge 1 + segmentSize: ge 10 segments: - segmentId: not null spans: @@ -23,303 +23,650 @@ segmentItems: parentSpanId: 0 spanId: 1 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} + - operationName: HEAD:/elasticsearch-case/case/healthCheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/elasticsearch-case/case/healthCheck'} + - {key: http.method, value: HEAD} + - {key: http.status_code, value: '200'} + - segmentId: not null + spans: + - operationName: Elasticsearch/CreateRequest/onResponse + parentSpanId: -1 + spanId: 0 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: transmission.latency, value: not null} + refs: + - {parentEndpoint: 'GET:/elasticsearch-case/case/elasticsearch', networkAddress: '', + refType: CrossThread, parentSpanId: 5, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: elasticsearch-7.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: Elasticsearch/IndexRequest/onResponse + parentSpanId: -1 + spanId: 0 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: transmission.latency, value: not null} + refs: + - {parentEndpoint: 'GET:/elasticsearch-case/case/elasticsearch', networkAddress: '', + refType: CrossThread, parentSpanId: 8, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: elasticsearch-7.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: Elasticsearch/RefreshRequest/onResponse + parentSpanId: -1 + spanId: 0 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: transmission.latency, value: not null} + refs: + - {parentEndpoint: 'GET:/elasticsearch-case/case/elasticsearch', networkAddress: '', + refType: CrossThread, parentSpanId: 9, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: elasticsearch-7.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: Elasticsearch/GetRequest/onResponse + parentSpanId: -1 + spanId: 0 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: transmission.latency, value: not null} + refs: + - {parentEndpoint: 'GET:/elasticsearch-case/case/elasticsearch', networkAddress: '', + refType: CrossThread, parentSpanId: 13, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: elasticsearch-7.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: Elasticsearch/SearchRequest/onResponse + parentSpanId: -1 + spanId: 0 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: transmission.latency, value: not null} + refs: + - {parentEndpoint: 'GET:/elasticsearch-case/case/elasticsearch', networkAddress: '', + refType: CrossThread, parentSpanId: 15, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: elasticsearch-7.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: Elasticsearch/UpdateRequest/onResponse + parentSpanId: -1 + spanId: 0 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: transmission.latency, value: not null} + refs: + - {parentEndpoint: 'GET:/elasticsearch-case/case/elasticsearch', networkAddress: '', + refType: CrossThread, parentSpanId: 17, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: elasticsearch-7.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: Elasticsearch/AnalyzeRequest/onResponse + parentSpanId: -1 + spanId: 0 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: transmission.latency, value: not null} + refs: + - {parentEndpoint: 'GET:/elasticsearch-case/case/elasticsearch', networkAddress: '', + refType: CrossThread, parentSpanId: 19, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: elasticsearch-7.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: Elasticsearch/DeleteRequest/onResponse + parentSpanId: -1 + spanId: 0 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: transmission.latency, value: not null} + refs: + - {parentEndpoint: 'GET:/elasticsearch-case/case/elasticsearch', networkAddress: '', + refType: CrossThread, parentSpanId: 21, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: elasticsearch-7.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: Elasticsearch/Health + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} - operationName: Elasticsearch/GetSettings parentSpanId: 0 spanId: 2 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} - operationName: Elasticsearch/PutSettings parentSpanId: 0 spanId: 3 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.statement, value: not null } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} + - {key: db.statement, value: not null} - operationName: Elasticsearch/CreateRequest parentSpanId: 0 spanId: 4 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - skipAnalysis: 'false' - - operationName: Elasticsearch/IndexRequest + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - operationName: Elasticsearch/CreateRequest parentSpanId: 0 spanId: 5 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' - - operationName: Elasticsearch/RefreshRequest + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - operationName: Elasticsearch/IndexRequest parentSpanId: 0 spanId: 6 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - skipAnalysis: 'false' - - operationName: Elasticsearch/GetRequest + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/RefreshRequest parentSpanId: 0 spanId: 7 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' - - operationName: Elasticsearch/SearchRequest + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - operationName: Elasticsearch/IndexRequest parentSpanId: 0 spanId: 8 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' - - operationName: Elasticsearch/UpdateRequest + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/RefreshRequest parentSpanId: 0 spanId: 9 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' - - operationName: Elasticsearch/AnalyzeRequest + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - operationName: Elasticsearch/RefreshRequest parentSpanId: 0 spanId: 10 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: analyzer, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' - - operationName: Elasticsearch/DeleteRequest + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - operationName: Elasticsearch/RefreshRequest parentSpanId: 0 spanId: 11 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 77 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - skipAnalysis: 'false' - - operationName: Elasticsearch/IndexRequest + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - operationName: Elasticsearch/GetRequest parentSpanId: 0 spanId: 12 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/GetRequest + parentSpanId: 0 + spanId: 13 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/SearchRequest + parentSpanId: 0 + spanId: 14 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/SearchRequest + parentSpanId: 0 + spanId: 15 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/UpdateRequest + parentSpanId: 0 + spanId: 16 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/UpdateRequest + parentSpanId: 0 + spanId: 17 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/AnalyzeRequest + parentSpanId: 0 + spanId: 18 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: analyzer, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/AnalyzeRequest + parentSpanId: 0 + spanId: 19 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: analyzer, value: not null} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/DeleteRequest + parentSpanId: 0 + spanId: 20 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - operationName: Elasticsearch/DeleteRequest + parentSpanId: 0 + spanId: 21 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - operationName: Elasticsearch/IndexRequest + parentSpanId: 0 + spanId: 22 + spanLayer: Database + startTime: not null + endTime: not null componentId: 48 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: node.address, value: not null } - - { key: es.indices, value: not null } - - { key: es.types, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: node.address, value: not null} + - {key: es.indices, value: not null} + - {key: es.types, value: not null} + - {key: db.statement, value: not null} - operationName: Elasticsearch/actionGet parentSpanId: 0 - spanId: 13 - startTime: nq 0 - endTime: nq 0 + spanId: 23 + spanLayer: Unknown + startTime: not null + endTime: not null componentId: 48 isError: false spanType: Local + peer: '' + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.statement, value: not null } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} + - {key: db.statement, value: not null} - operationName: Elasticsearch/GetRequest parentSpanId: 0 - spanId: 14 + spanId: 24 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 48 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: node.address, value: not null } - - { key: es.indices, value: not null } - - { key: es.types, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: node.address, value: not null} + - {key: es.indices, value: not null} + - {key: es.types, value: not null} + - {key: db.statement, value: not null} - operationName: Elasticsearch/SearchRequest parentSpanId: 0 - spanId: 15 + spanId: 25 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 48 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: node.address, value: not null } - - { key: es.indices, value: not null } - - { key: es.types, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: node.address, value: not null} + - {key: es.indices, value: not null} + - {key: es.types, value: not null} + - {key: db.statement, value: not null} - operationName: Elasticsearch/actionGet parentSpanId: 0 - spanId: 16 - startTime: nq 0 - endTime: nq 0 + spanId: 26 + spanLayer: Unknown + startTime: not null + endTime: not null componentId: 48 isError: false spanType: Local + peer: '' + skipAnalysis: false tags: - {key: db.type, value: Elasticsearch} - - {key: es.took_millis, value: not null } - - {key: es.total_hits, value: not null } - - {key: db.statement, value: not null } - skipAnalysis: 'false' + - {key: es.took_millis, value: not null} + - {key: es.total_hits, value: not null} + - {key: db.statement, value: not null} - operationName: Elasticsearch/UpdateRequest parentSpanId: 0 - spanId: 17 + spanId: 27 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 48 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: node.address, value: not null } - - { key: es.indices, value: not null } - - { key: es.types, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: node.address, value: not null} + - {key: es.indices, value: not null} + - {key: es.types, value: not null} + - {key: db.statement, value: not null} - operationName: Elasticsearch/DeleteRequest parentSpanId: 0 - spanId: 18 + spanId: 28 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 48 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: node.address, value: not null } - - { key: es.indices, value: not null } - - { key: es.types, value: not null } - - { key: db.statement, value: not null } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: node.address, value: not null} + - {key: es.indices, value: not null} + - {key: es.types, value: not null} + - {key: db.statement, value: not null} - operationName: Elasticsearch/DeleteIndexRequest parentSpanId: 0 - spanId: 19 + spanId: 29 spanLayer: Database - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 48 isError: false spanType: Exit peer: not null + skipAnalysis: false tags: - - { key: db.type, value: Elasticsearch } - - { key: db.instance, value: not null } - - { key: node.address, value: not null } - - { key: es.indices, value: not null } - skipAnalysis: 'false' + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: not null} + - {key: node.address, value: not null} + - {key: es.indices, value: not null} - operationName: GET:/elasticsearch-case/case/elasticsearch parentSpanId: -1 spanId: 0 spanLayer: Http - startTime: nq 0 - endTime: nq 0 + startTime: not null + endTime: not null componentId: 1 isError: false spanType: Entry peer: '' + skipAnalysis: false tags: - - { key: url, value: 'http://localhost:8080/elasticsearch-case/case/elasticsearch' } - - { key: http.method, value: GET } + - {key: url, value: 'http://localhost:8080/elasticsearch-case/case/elasticsearch'} + - {key: http.method, value: GET} - {key: http.status_code, value: '200'} - skipAnalysis: 'false' diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/RestHighLevelClientCase.java b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/RestHighLevelClientCase.java index ce44956346..a0314fae32 100644 --- a/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/RestHighLevelClientCase.java +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/RestHighLevelClientCase.java @@ -22,9 +22,11 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.concurrent.CountDownLatch; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.skywalking.apm.testcase.elasticsearch.controller.CaseController; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest; @@ -33,6 +35,7 @@ import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; +import org.elasticsearch.action.admin.indices.refresh.RefreshResponse; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; @@ -85,6 +88,7 @@ public String healthCheck() throws Exception { public String elasticsearch() throws Exception { String indexName = UUID.randomUUID().toString(); + String indexName2 = UUID.randomUUID().toString(); try { // health health(); @@ -97,27 +101,35 @@ public String elasticsearch() throws Exception { // create createIndex(indexName); + createIndexAsync(indexName2); // index index(indexName); + indexAsync(indexName2); // refresh client.indices().refresh(new RefreshRequest(indexName), RequestOptions.DEFAULT); + client.indices().refresh(new RefreshRequest(indexName2), RequestOptions.DEFAULT); // get get(indexName); + getAsync(indexName2); // search search(indexName); + searchAsync(indexName2); // update update(indexName); + updateAsync(indexName2); // analyze analyze(indexName); + analyzeAsync(indexName2); // delete delete(indexName); + deleteAsync(indexName2); } finally { if (null != client) { client.close(); @@ -189,6 +201,41 @@ private void createIndex(String indexName) throws IOException { } } + private void createIndexAsync(String indexName) throws InterruptedException { + CreateIndexRequest request = new CreateIndexRequest(indexName); + Map mapping = new HashMap<>(); + Map mappingProperties = new HashMap<>(); + Map mappingPropertiesAuthor = new HashMap<>(); + mappingPropertiesAuthor.put("type", "keyword"); + mappingProperties.put("author", mappingPropertiesAuthor); + Map mappingPropertiesTitle = new HashMap<>(); + mappingPropertiesTitle.put("type", "keyword"); + mappingProperties.put("title", mappingPropertiesTitle); + mapping.put("properties", mappingProperties); + request.mapping(mapping); + + request.settings(Settings.builder().put("index.number_of_shards", 1).put("index.number_of_replicas", 0)); + + final CountDownLatch latch = new CountDownLatch(1); + client.indices().createAsync(request, RequestOptions.DEFAULT, new ActionListener() { + @Override + public void onResponse(final CreateIndexResponse createIndexResponse) { + latch.countDown(); + if (!createIndexResponse.isAcknowledged()) { + String message = "elasticsearch create index fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + @Override + public void onFailure(final Exception e) { + latch.countDown(); + } + }); + latch.await(); + } + private void index(String indexName) throws IOException { Map source = new HashMap<>(); source.put("author", "Marker"); @@ -201,6 +248,49 @@ private void index(String indexName) throws IOException { LOGGER.error(message); throw new RuntimeException(message); } + client.indices().refresh(new RefreshRequest(indexName), RequestOptions.DEFAULT); + } + + private void indexAsync(String indexName) throws InterruptedException { + Map source = new HashMap<>(); + source.put("author", "Marker"); + source.put("title", "Java programing."); + IndexRequest indexRequest = new IndexRequest(indexName).id("1").source(source); + + final CountDownLatch latch = new CountDownLatch(2); + client.indexAsync(indexRequest, RequestOptions.DEFAULT, + new ActionListener() { + @Override + public void onResponse(final IndexResponse indexResponse) { + latch.countDown(); + if (indexResponse.status().getStatus() >= 400) { + String message = "elasticsearch index data fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + @Override + public void onFailure(final Exception e) { + latch.countDown(); + } + } + ); + + client.indices().refreshAsync(new RefreshRequest(indexName), RequestOptions.DEFAULT, + new ActionListener() { + @Override + public void onResponse(final RefreshResponse refreshResponse) { + latch.countDown(); + } + + @Override + public void onFailure(final Exception e) { + latch.countDown(); + } + } + ); + latch.await(); } private void get(String indexName) throws IOException { @@ -214,6 +304,31 @@ private void get(String indexName) throws IOException { } } + private void getAsync(String indexName) throws InterruptedException { + GetRequest getRequest = new GetRequest(indexName, "1"); + final CountDownLatch latch = new CountDownLatch(1); + client.getAsync(getRequest, RequestOptions.DEFAULT, + new ActionListener() { + @Override + public void onResponse(final GetResponse getResponse) { + latch.countDown(); + if (!getResponse.isExists()) { + String message = "elasticsearch get data fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + @Override + public void onFailure(final Exception e) { + latch.countDown(); + throw new RuntimeException(e); + } + } + ); + latch.await(); + } + private void update(String indexName) throws IOException { UpdateRequest request = new UpdateRequest(indexName, "1"); Map parameters = singletonMap("title", "c++ programing."); @@ -228,6 +343,33 @@ private void update(String indexName) throws IOException { } } + private void updateAsync(String indexName) throws InterruptedException { + UpdateRequest request = new UpdateRequest(indexName, "1"); + Map parameters = singletonMap("title", "c++ programing."); + Script inline = new Script(ScriptType.INLINE, "painless", "ctx._source.title = params.title", parameters); + request.script(inline); + + final CountDownLatch latch = new CountDownLatch(1); + client.updateAsync(request, RequestOptions.DEFAULT, new ActionListener() { + @Override + public void onResponse(final UpdateResponse updateResponse) { + latch.countDown(); + if (updateResponse.getVersion() != 2) { + String message = "elasticsearch update data fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + @Override + public void onFailure(final Exception e) { + latch.countDown(); + throw new RuntimeException(e); + } + }); + latch.await(); + } + private void analyze(String indexName) throws IOException { AnalyzeRequest analyzeRequest = AnalyzeRequest.withIndexAnalyzer(indexName, null, "SkyWalking"); AnalyzeResponse analyzeResponse = client.indices().analyze(analyzeRequest, RequestOptions.DEFAULT); @@ -238,6 +380,30 @@ private void analyze(String indexName) throws IOException { } } + private void analyzeAsync(String indexName) throws InterruptedException { + AnalyzeRequest analyzeRequest = AnalyzeRequest.withIndexAnalyzer(indexName, null, "SkyWalking"); + final CountDownLatch latch = new CountDownLatch(1); + client.indices().analyzeAsync( + analyzeRequest, RequestOptions.DEFAULT, new ActionListener() { + @Override + public void onResponse(final AnalyzeResponse analyzeResponse) { + latch.countDown(); + if (null == analyzeResponse.getTokens() || analyzeResponse.getTokens().size() < 1) { + String message = "elasticsearch analyze index fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + @Override + public void onFailure(final Exception e) { + latch.countDown(); + LOGGER.error(e); + } + }); + latch.await(); + } + private void delete(String indexName) throws IOException { DeleteIndexRequest request = new DeleteIndexRequest(indexName); AcknowledgedResponse deleteIndexResponse = client.indices().delete(request, RequestOptions.DEFAULT); @@ -248,6 +414,29 @@ private void delete(String indexName) throws IOException { } } + private void deleteAsync(String indexName) throws InterruptedException { + DeleteIndexRequest request = new DeleteIndexRequest(indexName); + final CountDownLatch latch = new CountDownLatch(1); + client.indices().deleteAsync(request, RequestOptions.DEFAULT, new ActionListener() { + @Override + public void onResponse(final AcknowledgedResponse acknowledgedResponse) { + latch.countDown(); + if (!acknowledgedResponse.isAcknowledged()) { + String message = "elasticsearch delete index fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + @Override + public void onFailure(final Exception e) { + latch.countDown(); + throw new RuntimeException(e); + } + }); + latch.await(); + } + private void search(String indexName) throws IOException { SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.query(QueryBuilders.termQuery("author", "Marker")); @@ -266,4 +455,35 @@ private void search(String indexName) throws IOException { throw new RuntimeException(message); } } + + private void searchAsync(String indexName) throws InterruptedException { + SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); + sourceBuilder.query(QueryBuilders.termQuery("author", "Marker")); + sourceBuilder.from(0); + sourceBuilder.size(10); + + SearchRequest searchRequest = new SearchRequest(); + searchRequest.indices(indexName); + searchRequest.source(sourceBuilder); + final CountDownLatch latch = new CountDownLatch(1); + client.searchAsync(searchRequest, RequestOptions.DEFAULT, new ActionListener() { + @Override + public void onResponse(final SearchResponse searchResponse) { + latch.countDown(); + int length = searchResponse.getHits().getHits().length; + if (!(length > 0)) { + String message = "elasticsearch search data fail."; + LOGGER.error(message); + throw new RuntimeException(message); + } + } + + @Override + public void onFailure(final Exception e) { + latch.countDown(); + LOGGER.error(e); + } + }); + latch.await(); + } } diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/support-version.list b/test/plugin/scenarios/elasticsearch-7.x-scenario/support-version.list index 54e1c1de5b..d5108d7a3c 100644 --- a/test/plugin/scenarios/elasticsearch-7.x-scenario/support-version.list +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/support-version.list @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# 7.0.0 - 7.17.12 have been tested, and 7.0.0 - 7.2.1 not included in the test 7.3.2 7.4.2 7.5.2 @@ -27,4 +28,4 @@ 7.13.4 7.14.2 7.16.3 -7.17.12 \ No newline at end of file +7.17.21 \ No newline at end of file From 313d7d5c8e171df0a24b273c4949738133586922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E6=A0=BC=E8=8B=8F=E6=A0=BC=E6=8B=89?= Date: Mon, 3 Jun 2024 11:22:17 +0800 Subject: [PATCH 017/114] Fix to Ensure not isInterface requirement applied to all conditions (#695) --- CHANGES.md | 1 + .../apache/skywalking/apm/agent/core/plugin/PluginFinder.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 321c775094..0be603455f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ Release Notes. * Support for showing batch command details and ignoring PING commands in Redisson plugin. * Fix peer value of Master-Slave mode in Redisson plugin. * Support for tracing the callbacks of asynchronous methods in elasticsearch-6.x-plugin/elasticsearch-7.x-plugin. +* Fixed the invalid issue in the isInterface method in PluginFinder. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) 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 4ef608dccc..5a7404e729 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 @@ -95,13 +95,14 @@ public boolean matches(NamedElement target) { return nameMatchDefine.containsKey(target.getActualName()); } }; - judge = judge.and(not(isInterface())); for (AbstractClassEnhancePluginDefine define : signatureMatchDefine) { ClassMatch match = define.enhanceClass(); if (match instanceof IndirectMatch) { judge = judge.or(((IndirectMatch) match).buildJunction()); } } + // Filter out all matchers returns to exclude pure interface types. + judge = not(isInterface()).and(judge); return new ProtectiveShieldMatcher(judge); } From 3a9645849529736ca3f67170d673daaee0ed0cda Mon Sep 17 00:00:00 2001 From: xiaqi1210 Date: Thu, 6 Jun 2024 17:33:07 +0800 Subject: [PATCH 018/114] Fix the opentracing toolkit SPI config (#696) --- CHANGES.md | 1 + .../services}/io.opentracing.Tracer | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename apm-application-toolkit/apm-toolkit-opentracing/src/main/resources/{META-INF.services => META-INF/services}/io.opentracing.Tracer (92%) diff --git a/CHANGES.md b/CHANGES.md index 0be603455f..c7d88b0784 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ Release Notes. * Fix peer value of Master-Slave mode in Redisson plugin. * Support for tracing the callbacks of asynchronous methods in elasticsearch-6.x-plugin/elasticsearch-7.x-plugin. * Fixed the invalid issue in the isInterface method in PluginFinder. +* Fix the opentracing toolkit SPI config All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-application-toolkit/apm-toolkit-opentracing/src/main/resources/META-INF.services/io.opentracing.Tracer b/apm-application-toolkit/apm-toolkit-opentracing/src/main/resources/META-INF/services/io.opentracing.Tracer similarity index 92% rename from apm-application-toolkit/apm-toolkit-opentracing/src/main/resources/META-INF.services/io.opentracing.Tracer rename to apm-application-toolkit/apm-toolkit-opentracing/src/main/resources/META-INF/services/io.opentracing.Tracer index 894da6a64f..4cb914e314 100644 --- a/apm-application-toolkit/apm-toolkit-opentracing/src/main/resources/META-INF.services/io.opentracing.Tracer +++ b/apm-application-toolkit/apm-toolkit-opentracing/src/main/resources/META-INF/services/io.opentracing.Tracer @@ -16,4 +16,4 @@ # # -org.apache.skywalking.apm.toolkit.opentracing.SkyWalkingTracer +org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer From e54d8a534cd291b8e13d09d335bde1471b9c6208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Sat, 22 Jun 2024 09:36:26 +0800 Subject: [PATCH 019/114] Remove Oracle scenario from testing. (#699) --- .github/workflows/plugins-test.3.yaml | 1 - .../scenarios/oracle-scenario/bin/startup.sh | 21 --- .../oracle-scenario/config/expectedData.yaml | 113 -------------- .../oracle-scenario/configuration.yml | 30 ---- test/plugin/scenarios/oracle-scenario/pom.xml | 121 --------------- .../src/main/assembly/assembly.xml | 41 ------ .../apm/testcase/oracle/Application.java | 34 ----- .../oracle/controller/CaseController.java | 139 ------------------ .../src/main/resources/application.yaml | 23 --- .../src/main/resources/log4j2.xml | 30 ---- .../oracle-scenario/support-version.list | 17 --- 11 files changed, 570 deletions(-) delete mode 100644 test/plugin/scenarios/oracle-scenario/bin/startup.sh delete mode 100644 test/plugin/scenarios/oracle-scenario/config/expectedData.yaml delete mode 100644 test/plugin/scenarios/oracle-scenario/configuration.yml delete mode 100644 test/plugin/scenarios/oracle-scenario/pom.xml delete mode 100644 test/plugin/scenarios/oracle-scenario/src/main/assembly/assembly.xml delete mode 100644 test/plugin/scenarios/oracle-scenario/src/main/java/org/apache/skywalking/apm/testcase/oracle/Application.java delete mode 100644 test/plugin/scenarios/oracle-scenario/src/main/java/org/apache/skywalking/apm/testcase/oracle/controller/CaseController.java delete mode 100644 test/plugin/scenarios/oracle-scenario/src/main/resources/application.yaml delete mode 100644 test/plugin/scenarios/oracle-scenario/src/main/resources/log4j2.xml delete mode 100644 test/plugin/scenarios/oracle-scenario/support-version.list diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index e687161731..264529fdd3 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -92,7 +92,6 @@ jobs: - gateway-3.x-scenario - gateway-3.x-filter-context-scenario - neo4j-4.x-scenario - - oracle-scenario - druid-1.x-scenario - hikaricp-scenario - clickhouse-0.3.1-scenario diff --git a/test/plugin/scenarios/oracle-scenario/bin/startup.sh b/test/plugin/scenarios/oracle-scenario/bin/startup.sh deleted file mode 100644 index a8f932fa0d..0000000000 --- a/test/plugin/scenarios/oracle-scenario/bin/startup.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/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/oracle-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/oracle-scenario/config/expectedData.yaml b/test/plugin/scenarios/oracle-scenario/config/expectedData.yaml deleted file mode 100644 index 91df4be88d..0000000000 --- a/test/plugin/scenarios/oracle-scenario/config/expectedData.yaml +++ /dev/null @@ -1,113 +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. -segmentItems: -- serviceName: oracle-scenario - segmentSize: ge 1 - segments: - - segmentId: not null - spans: - - operationName: Oracle/JDBC/Statement/execute - parentSpanId: 0 - spanId: 1 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 34 - isError: false - spanType: Exit - peer: oracle-server:1521 - tags: - - {key: db.type, value: Oracle} - - {key: db.instance, value: xe} - - key: db.statement - value: "CREATE TABLE test_007(\nid VARCHAR(1) PRIMARY KEY, \nvalue VARCHAR(1)\ - \ NOT NULL)" - skipAnalysis: 'false' - - operationName: Oracle/JDBC/PreparedStatement/execute - parentSpanId: 0 - spanId: 2 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 34 - isError: false - spanType: Exit - peer: oracle-server:1521 - tags: - - {key: db.type, value: Oracle} - - {key: db.instance, value: xe} - - {key: db.statement, value: 'INSERT INTO test_007(id, value) VALUES(?,?)'} - skipAnalysis: 'false' - - operationName: Oracle/JDBC/PreparedStatement/executeQuery - parentSpanId: 0 - spanId: 3 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 34 - isError: false - spanType: Exit - peer: oracle-server:1521 - tags: - - {key: db.type, value: Oracle} - - {key: db.instance, value: xe} - - {key: db.statement, value: 'SELECT id, value FROM test_007 WHERE id=?'} - skipAnalysis: 'false' - - operationName: Oracle/JDBC/Statement/execute - parentSpanId: 0 - spanId: 4 - spanLayer: Database - startTime: nq 0 - endTime: nq 0 - componentId: 34 - isError: false - spanType: Exit - peer: oracle-server:1521 - tags: - - {key: db.type, value: Oracle} - - {key: db.instance, value: xe} - - {key: db.statement, value: DROP table test_007} - skipAnalysis: 'false' - - operationName: Oracle/JDBC/Connection/close - parentSpanId: 0 - spanId: 5 - spanLayer: Database - tags: - - {key: db.type, value: Oracle} - - {key: db.instance, value: xe} - - {key: db.statement, value: ''} - startTime: nq 0 - endTime: nq 0 - componentId: 34 - isError: false - spanType: Exit - peer: oracle-server:1521 - skipAnalysis: 'false' - - operationName: GET:/oracle-scenario/case/oracle - parentSpanId: -1 - spanId: 0 - spanLayer: Http - startTime: nq 0 - endTime: nq 0 - componentId: 1 - isError: false - spanType: Entry - peer: '' - tags: - - {key: url, value: 'http://localhost:8080/oracle-scenario/case/oracle'} - - {key: http.method, value: GET} - - {key: http.status_code, value: '200'} - skipAnalysis: 'false' diff --git a/test/plugin/scenarios/oracle-scenario/configuration.yml b/test/plugin/scenarios/oracle-scenario/configuration.yml deleted file mode 100644 index 0b112b9e7b..0000000000 --- a/test/plugin/scenarios/oracle-scenario/configuration.yml +++ /dev/null @@ -1,30 +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. - -type: jvm -entryService: http://localhost:8080/oracle-scenario/case/oracle -healthCheck: http://localhost:8080/oracle-scenario/case/healthCheck -startScript: ./bin/startup.sh -environment: - - oracle.address=oracle-server:1521 - - oracle.username=system - - oracle.password=oracle -dependencies: - oracle-server: - image: deepdiver/docker-oracle-xe-11g - hostname: oracle-server - expose: - - "1521" diff --git a/test/plugin/scenarios/oracle-scenario/pom.xml b/test/plugin/scenarios/oracle-scenario/pom.xml deleted file mode 100644 index ed087a9cca..0000000000 --- a/test/plugin/scenarios/oracle-scenario/pom.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - org.apache.skywalking.apm.testcase - oracle-scenario - 1.0.0 - jar - - 4.0.0 - - - UTF-8 - 1.8 - 3.8.1 - - 10.2.0.4.0 - - 2.1.6.RELEASE - - - skywalking-oracle-scenario - - - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - - - - - com.oracle - ojdbc14 - ${test.framework.version} - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-logging - - - - - org.springframework.boot - spring-boot-starter-log4j2 - - - - - oracle-scenario - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - - repackage - - - - - - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${compiler.version} - ${compiler.version} - ${project.build.sourceEncoding} - - - - org.apache.maven.plugins - maven-assembly-plugin - - - assemble - package - - single - - - - src/main/assembly/assembly.xml - - ./target/ - - - - - - - diff --git a/test/plugin/scenarios/oracle-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/oracle-scenario/src/main/assembly/assembly.xml deleted file mode 100644 index 9e4db94d75..0000000000 --- a/test/plugin/scenarios/oracle-scenario/src/main/assembly/assembly.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - zip - - - - - ./bin - 0775 - - - - - - ${project.build.directory}/oracle-scenario.jar - ./libs - 0775 - - - diff --git a/test/plugin/scenarios/oracle-scenario/src/main/java/org/apache/skywalking/apm/testcase/oracle/Application.java b/test/plugin/scenarios/oracle-scenario/src/main/java/org/apache/skywalking/apm/testcase/oracle/Application.java deleted file mode 100644 index 31bce49f55..0000000000 --- a/test/plugin/scenarios/oracle-scenario/src/main/java/org/apache/skywalking/apm/testcase/oracle/Application.java +++ /dev/null @@ -1,34 +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.testcase.oracle; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class Application { - - public static void main(String[] args) { - try { - SpringApplication.run(Application.class, args); - } catch (Exception e) { - // Never do this - } - } -} diff --git a/test/plugin/scenarios/oracle-scenario/src/main/java/org/apache/skywalking/apm/testcase/oracle/controller/CaseController.java b/test/plugin/scenarios/oracle-scenario/src/main/java/org/apache/skywalking/apm/testcase/oracle/controller/CaseController.java deleted file mode 100644 index c3bb2d2aa9..0000000000 --- a/test/plugin/scenarios/oracle-scenario/src/main/java/org/apache/skywalking/apm/testcase/oracle/controller/CaseController.java +++ /dev/null @@ -1,139 +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.testcase.oracle.controller; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import javax.annotation.PostConstruct; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/case") -public class CaseController { - - private static final Logger LOGGER = LogManager.getLogger(CaseController.class); - - @Value("${oracle.address}") - private String oracleHostAndPort; - - @Value("${oracle.username}") - private String oracleUsername; - - @Value("${oracle.password}") - private String oraclePassword; - - private String connectURL; - private static final String TEST_EXIST_SQL = "SELECT * FROM dual"; - private static final String CREATE_TABLE_SQL = "CREATE TABLE test_007(\n" + "id VARCHAR(1) PRIMARY KEY, \n" + "value VARCHAR(1) NOT NULL)"; - private static final String INSERT_DATA_SQL = "INSERT INTO test_007(id, value) VALUES(?,?)"; - private static final String QUERY_DATA_SQL = "SELECT id, value FROM test_007 WHERE id=?"; - private static final String DROP_TABLE_SQL = "DROP table test_007"; - - private static final String SUCCESS = "Success"; - - @PostConstruct - public void setUp() throws ClassNotFoundException { - Class.forName("oracle.jdbc.driver.OracleDriver"); - connectURL = "jdbc:oracle:thin:@" + oracleHostAndPort + ":xe"; - } - - @RequestMapping("/oracle") - @ResponseBody - public String testcase() { - Connection connection = null; - try { - // create table by using statement - connection = DriverManager.getConnection(connectURL, oracleUsername, oraclePassword); - Statement statement = connection.createStatement(); - statement.execute(CREATE_TABLE_SQL); - statement.close(); - - // insert table by using PreparedStatement - PreparedStatement insertDataPreparedStatement = connection.prepareStatement(INSERT_DATA_SQL); - insertDataPreparedStatement.setString(1, "1"); - insertDataPreparedStatement.setString(2, "1"); - insertDataPreparedStatement.execute(); - insertDataPreparedStatement.close(); - - // query data by using PreparedStatement - PreparedStatement queryDataPreparedStatement = connection.prepareStatement(QUERY_DATA_SQL); - queryDataPreparedStatement.setString(1, "1"); - ResultSet resultSet = queryDataPreparedStatement.executeQuery(); - resultSet.next(); - LOGGER.info("Query id[{}]: value={}", "1", resultSet.getString(2)); - queryDataPreparedStatement.close(); - - // drop table by using statement - Statement dropTableStatement = connection.createStatement(); - dropTableStatement.execute(DROP_TABLE_SQL); - dropTableStatement.close(); - } catch (SQLException e) { - String message = "Failed to execute sql"; - LOGGER.error(message); - throw new RuntimeException(message); - } finally { - if (connection != null) { - try { - connection.close(); - } catch (SQLException e) { - String message = "Failed to close connection"; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - } - return SUCCESS; - } - - @RequestMapping("/healthCheck") - @ResponseBody - public String healthCheck() { - Connection connection = null; - try { - connection = DriverManager.getConnection(connectURL, oracleUsername, oraclePassword); - PreparedStatement preparedStatement = connection.prepareStatement(TEST_EXIST_SQL); - preparedStatement.execute(); - preparedStatement.close(); - } catch (SQLException e) { - String message = "Failed to execute sql"; - LOGGER.error(message); - throw new RuntimeException(message); - } finally { - if (connection != null) { - try { - connection.close(); - } catch (SQLException e) { - String message = "Failed to close connection"; - LOGGER.error(message); - throw new RuntimeException(message); - } - } - } - return SUCCESS; - } -} diff --git a/test/plugin/scenarios/oracle-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/oracle-scenario/src/main/resources/application.yaml deleted file mode 100644 index 3bf1f53f66..0000000000 --- a/test/plugin/scenarios/oracle-scenario/src/main/resources/application.yaml +++ /dev/null @@ -1,23 +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. -# -# -server: - port: 8080 - servlet: - context-path: /oracle-scenario -logging: - config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/oracle-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/oracle-scenario/src/main/resources/log4j2.xml deleted file mode 100644 index 9849ed5a8a..0000000000 --- a/test/plugin/scenarios/oracle-scenario/src/main/resources/log4j2.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/plugin/scenarios/oracle-scenario/support-version.list b/test/plugin/scenarios/oracle-scenario/support-version.list deleted file mode 100644 index 58b2e2f6dd..0000000000 --- a/test/plugin/scenarios/oracle-scenario/support-version.list +++ /dev/null @@ -1,17 +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. - -10.2.0.4.0 From 8200cf2b5194f31981249351b1e306e8b2303a45 Mon Sep 17 00:00:00 2001 From: jiangyunpeng Date: Sat, 22 Jun 2024 10:34:41 +0800 Subject: [PATCH 020/114] Improve 4x performance of ContextManagerExtendService.createTraceContext() (#698) --- CHANGES.md | 1 + apm-sniffer/apm-agent-core/pom.xml | 5 + .../context/ContextManagerExtendService.java | 14 ++- .../core/context/IgnoreSuffixBenchmark.java | 117 ++++++++++++++++++ 4 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/IgnoreSuffixBenchmark.java diff --git a/CHANGES.md b/CHANGES.md index c7d88b0784..54f7900e25 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Release Notes. * Support for tracing the callbacks of asynchronous methods in elasticsearch-6.x-plugin/elasticsearch-7.x-plugin. * Fixed the invalid issue in the isInterface method in PluginFinder. * Fix the opentracing toolkit SPI config +* Improve 4x performance of ContextManagerExtendService.createTraceContext() All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index 132e2dbfd0..2ea7df432e 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -138,6 +138,11 @@ org.slf4j slf4j-api + + org.openjdk.jmh + jmh-generator-annprocess + test + diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java index 1e408df81b..49faebdc0c 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java @@ -18,7 +18,10 @@ package org.apache.skywalking.apm.agent.core.context; -import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.apache.skywalking.apm.agent.core.boot.BootService; import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor; import org.apache.skywalking.apm.agent.core.boot.ServiceManager; @@ -35,7 +38,7 @@ @DefaultImplementor public class ContextManagerExtendService implements BootService, GRPCChannelListener { - private volatile String[] ignoreSuffixArray = new String[0]; + private volatile Set ignoreSuffixSet; private volatile GRPCChannelStatus status = GRPCChannelStatus.DISCONNECT; @@ -50,7 +53,7 @@ public void prepare() { @Override public void boot() { - ignoreSuffixArray = Config.Agent.IGNORE_SUFFIX.split(","); + ignoreSuffixSet = Stream.of(Config.Agent.IGNORE_SUFFIX.split(",")).collect(Collectors.toSet()); ignoreSuffixPatternsWatcher = new IgnoreSuffixPatternsWatcher("agent.ignore_suffix", this); spanLimitWatcher = new SpanLimitWatcher("agent.span_limit_per_segment"); @@ -82,8 +85,7 @@ public AbstractTracerContext createTraceContext(String operationName, boolean fo } int suffixIdx = operationName.lastIndexOf("."); - if (suffixIdx > -1 && Arrays.stream(ignoreSuffixArray) - .anyMatch(a -> a.equals(operationName.substring(suffixIdx)))) { + if (suffixIdx > -1 && ignoreSuffixSet.contains(operationName.substring(suffixIdx))) { context = new IgnoredTracerContext(); } else { SamplingService samplingService = ServiceManager.INSTANCE.findService(SamplingService.class); @@ -104,7 +106,7 @@ public void statusChanged(final GRPCChannelStatus status) { public void handleIgnoreSuffixPatternsChanged() { if (StringUtil.isNotBlank(ignoreSuffixPatternsWatcher.getIgnoreSuffixPatterns())) { - ignoreSuffixArray = ignoreSuffixPatternsWatcher.getIgnoreSuffixPatterns().split(","); + ignoreSuffixSet = Stream.of(ignoreSuffixPatternsWatcher.getIgnoreSuffixPatterns().split(",")).collect(Collectors.toSet()); } } } diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/IgnoreSuffixBenchmark.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/IgnoreSuffixBenchmark.java new file mode 100644 index 0000000000..623d674d06 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/IgnoreSuffixBenchmark.java @@ -0,0 +1,117 @@ +/* + * 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.agent.core.context; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import org.openjdk.jmh.runner.options.TimeValue; + +import java.util.Arrays; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * ISSUE-12355 + */ +@State(Scope.Benchmark) +@BenchmarkMode({Mode.Throughput, Mode.SampleTime}) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class IgnoreSuffixBenchmark { + public static String IGNORE_SUFFIX = ".jpg,.jpeg,.js,.css,.png,.bmp,.gif,.ico,.mp3,.mp4,.html,.svg"; + private String[] ignoreSuffixArray; + private Set ignoreSuffixSet; + + private String operationName = "test.api"; + + @Setup + public void setup() { + ignoreSuffixArray = IGNORE_SUFFIX.split(","); + ignoreSuffixSet = Stream.of(ignoreSuffixArray).collect(Collectors.toSet()); + } + + @Benchmark + public boolean testArray() { + int suffixIdx = operationName.lastIndexOf("."); + return Arrays.stream(ignoreSuffixArray) + .anyMatch(a -> a.equals(operationName.substring(suffixIdx))); + } + + @Benchmark + public boolean testHashSet() { + int suffixIdx = operationName.lastIndexOf("."); + return ignoreSuffixSet.contains(operationName.substring(suffixIdx)); + } + + public static void main(String[] args) throws Exception { + Options opt = new OptionsBuilder() + .include(IgnoreSuffixBenchmark.class.getName()) + .warmupIterations(3) + .warmupTime(TimeValue.seconds(10)) + .measurementIterations(3) + .measurementTime(TimeValue.seconds(10)) + .forks(1) + .build(); + new Runner(opt).run(); + } + /** + * # JMH version: 1.33 + * # VM version: JDK 11.0.21, Java HotSpot(TM) 64-Bit Server VM, 11.0.21+9-LTS-193 + * # VM invoker: /Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/bin/java + * # VM options: -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=60939:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 + * # Blackhole mode: full + dont-inline hint (default, use -Djmh.blackhole.autoDetect=true to auto-detect) + * # Warmup: 3 iterations, 10 s each + * # Measurement: 3 iterations, 10 s each + * # Timeout: 10 min per iteration + * # Threads: 1 thread, will synchronize iterations + * # Benchmark mode: Sampling time + * # Benchmark: org.apache.skywalking.apm.agent.core.context.IgnoreSuffixBenchmark.testHashSet + * + * Benchmark Mode Cnt Score Error Units + * IgnoreSuffixBenchmark.testArray thrpt 3 0.007 ± 0.003 ops/ns + * IgnoreSuffixBenchmark.testHashSet thrpt 3 0.084 ± 0.035 ops/ns + * IgnoreSuffixBenchmark.testArray sample 823984 183.234 ± 11.201 ns/op + * IgnoreSuffixBenchmark.testArray:testArray·p0.00 sample 41.000 ns/op + * IgnoreSuffixBenchmark.testArray:testArray·p0.50 sample 166.000 ns/op + * IgnoreSuffixBenchmark.testArray:testArray·p0.90 sample 167.000 ns/op + * IgnoreSuffixBenchmark.testArray:testArray·p0.95 sample 209.000 ns/op + * IgnoreSuffixBenchmark.testArray:testArray·p0.99 sample 375.000 ns/op + * IgnoreSuffixBenchmark.testArray:testArray·p0.999 sample 1124.630 ns/op + * IgnoreSuffixBenchmark.testArray:testArray·p0.9999 sample 29971.248 ns/op + * IgnoreSuffixBenchmark.testArray:testArray·p1.00 sample 1130496.000 ns/op + * IgnoreSuffixBenchmark.testHashSet sample 972621 27.117 ± 1.788 ns/op + * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.00 sample ≈ 0 ns/op + * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.50 sample 41.000 ns/op + * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.90 sample 42.000 ns/op + * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.95 sample 42.000 ns/op + * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.99 sample 83.000 ns/op + * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.999 sample 167.000 ns/op + * IgnoreSuffixBenchmark.testHashSet:testHashSet·p0.9999 sample 6827.950 ns/op + * IgnoreSuffixBenchmark.testHashSet:testHashSet·p1.00 sample 478208.000 ns/op + */ +} From 01248a20632f95e4cb6a8eec08b22b814e058319 Mon Sep 17 00:00:00 2001 From: Ricehomesky <63052374+Ricehomesky@users.noreply.github.com> Date: Mon, 24 Jun 2024 08:48:15 +0800 Subject: [PATCH 021/114] Fix problem which lead redisson plugin to throw unnecessary NullPointerException (#700) --- .../v3/RedisConnectionMethodInterceptor.java | 29 +++++++++++-------- .../RedisConnectionInstrumentation.java | 14 ++++----- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java index f660ca1a15..d475382c8f 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java @@ -19,6 +19,8 @@ package org.apache.skywalking.apm.plugin.redisson.v3; import io.netty.channel.Channel; + +import java.util.Objects; import java.util.stream.Collectors; import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.context.tag.Tags; @@ -28,8 +30,8 @@ import org.apache.skywalking.apm.agent.core.logging.api.LogManager; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; -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.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.redisson.v3.util.ClassUtil; import org.apache.skywalking.apm.util.StringUtil; @@ -42,17 +44,17 @@ import java.net.InetSocketAddress; import java.util.Optional; -public class RedisConnectionMethodInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { +public class RedisConnectionMethodInterceptor implements InstanceMethodsAroundInterceptorV2, InstanceConstructorInterceptor { private static final ILog LOGGER = LogManager.getLogger(RedisConnectionMethodInterceptor.class); private static final String ABBR = "..."; private static final String QUESTION_MARK = "?"; private static final String DELIMITER_SPACE = " "; + public static final Object STOP_SPAN_FLAG = new Object(); @Override - public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInvocationContext context) throws Throwable { String peer = (String) objInst.getSkyWalkingDynamicField(); RedisConnection connection = (RedisConnection) objInst; @@ -82,6 +84,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } AbstractSpan span = ContextManager.createExitSpan(operationName, peer); + context.setContext(STOP_SPAN_FLAG); span.setComponent(ComponentsDefine.REDISSON); Tags.CACHE_TYPE.set(span, "Redis"); Tags.CACHE_INSTANCE.set(span, dbInstance); @@ -93,17 +96,19 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } @Override - public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - Object ret) throws Throwable { - ContextManager.stopSpan(); + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret, MethodInvocationContext context) throws Throwable { + if (Objects.nonNull(context.getContext())) { + ContextManager.stopSpan(); + } return ret; } @Override - public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t) { - AbstractSpan span = ContextManager.activeSpan(); - span.log(t); + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { + if (Objects.nonNull(context.getContext())) { + AbstractSpan span = ContextManager.activeSpan(); + span.log(t); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisConnectionInstrumentation.java index 84bc82535f..34678af6b7 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisConnectionInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisConnectionInstrumentation.java @@ -21,15 +21,15 @@ 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.interceptor.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point; import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import static net.bytebuddy.matcher.ElementMatchers.named; import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; -public class RedisConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { +public class RedisConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 { private static final String ENHANCE_CLASS = "org.redisson.client.RedisConnection"; @@ -53,16 +53,16 @@ public String getConstructorInterceptor() { } @Override - public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[] { - new InstanceMethodsInterceptPoint() { + public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { + return new InstanceMethodsInterceptV2Point[] { + new InstanceMethodsInterceptV2Point() { @Override public ElementMatcher getMethodsMatcher() { return named("send"); } @Override - public String getMethodsInterceptor() { + public String getMethodsInterceptorV2() { return REDISSON_METHOD_INTERCEPTOR_CLASS; } From 002a4557c42a6b8d762e2c11b3d6af5a4d313be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Mon, 24 Jun 2024 09:40:05 +0800 Subject: [PATCH 022/114] Fix RESTEasy link 404 (#701) --- docs/en/setup/service-agent/java-agent/Supported-list.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 42a9c67539..99bd79d37d 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -17,7 +17,7 @@ metrics based on the tracing data. * [Jetty Server](http://www.eclipse.org/jetty/) 9.x -> 11.x * [Spring WebFlux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) 5.x (Optional¹) -> 6.x (Optional¹) * [Undertow](http://undertow.io/) 1.3.0.Final -> 2.0.27.Final - * [RESTEasy](https://resteasy.github.io/) 3.1.0.Final -> 6.2.4.Final + * [RESTEasy](https://resteasy.dev/) 3.1.0.Final -> 6.2.4.Final * [Play Framework](https://www.playframework.com/) 2.6.x -> 2.8.x * [Light4J Microservices Framework](https://doc.networknt.com/) 1.6.x -> 2.x * [Netty SocketIO](https://github.com/mrniko/netty-socketio) 1.x From 0fc3cd86e8c2261bedb417f971e319e5d582e4af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AF=BB=E6=89=BE=E7=9A=84=E4=BA=BA?= <1312544013@qq.com> Date: Sat, 29 Jun 2024 09:44:23 +0800 Subject: [PATCH 023/114] Add a plugin that supports the Solon framework. (#697) --- .github/workflows/plugins-test.3.yaml | 1 + CHANGES.md | 2 + .../trace/component/ComponentsDefine.java | 1 + apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../apm-sdk-plugin/solon-2.x-plugin/pom.xml | 48 ++++++++ .../solon/SolonActionExecuteInterceptor.java | 104 +++++++++++++++++ .../apm/plugin/solon/SolonPluginConfig.java | 43 +++++++ .../define/SolonActionInstrumentation.java | 66 +++++++++++ .../src/main/resources/skywalking-plugin.def | 17 +++ apm-sniffer/config/agent.config | 6 + .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 1 + .../java-agent/configurations.md | 5 +- .../solon-2.x-scenario/bin/startup.sh | 21 ++++ .../config/expectedData.yaml | 99 +++++++++++++++++ .../solon-2.x-scenario/configuration.yml | 20 ++++ .../scenarios/solon-2.x-scenario/pom.xml | 105 ++++++++++++++++++ .../src/main/assembly/assembly.xml | 41 +++++++ .../skywalking/apm/testcase/sc/solon/App.java | 29 +++++ .../sc/solon/controller/Controller.java | 55 +++++++++ .../sc/solon/service/TestService.java | 43 +++++++ .../src/main/resources/app.yml | 18 +++ .../solon-2.x-scenario/support-version.list | 18 +++ 23 files changed, 744 insertions(+), 1 deletion(-) create mode 100644 apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/SolonActionExecuteInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/SolonPluginConfig.java create mode 100644 apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/define/SolonActionInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 test/plugin/scenarios/solon-2.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/solon-2.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/solon-2.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/solon-2.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/solon-2.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/App.java create mode 100644 test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/controller/Controller.java create mode 100644 test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/service/TestService.java create mode 100644 test/plugin/scenarios/solon-2.x-scenario/src/main/resources/app.yml create mode 100644 test/plugin/scenarios/solon-2.x-scenario/support-version.list diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index 264529fdd3..5960da690a 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -107,6 +107,7 @@ jobs: - grpc-generic-call-scenario - shenyu-2.4.x-grpc-scenario - shenyu-2.4.x-sofarpc-scenario + - solon-2.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 54f7900e25..f80f1f151b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,8 @@ Release Notes. * Fixed the invalid issue in the isInterface method in PluginFinder. * Fix the opentracing toolkit SPI config * Improve 4x performance of ContextManagerExtendService.createTraceContext() +* Add a plugin that supports the Solon framework. + All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index b7307ebac7..101abcdb5e 100755 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -257,5 +257,6 @@ public class ComponentsDefine { public static final OfficialComponent OCEANBASE_JDBC_DRIVER = new OfficialComponent(157, "OceanBase-jdbc-driver"); + public static final OfficialComponent SOLON_MVC = new OfficialComponent(158, "SolonMVC"); } diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index bce4312dfc..bc2aa1f68c 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -137,6 +137,7 @@ rocketMQ-client-java-5.x-plugin activemq-artemis-jakarta-client-2.x-plugin c3p0-0.9.x-plugin + solon-2.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml new file mode 100644 index 0000000000..ca4dc473d2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml @@ -0,0 +1,48 @@ + + + + + 4.0.0 + + apm-sdk-plugin + org.apache.skywalking + 9.3.0-SNAPSHOT + + + solon-2.x-plugin + jar + + solon-2.x-plugin + http://maven.apache.org + + + UTF-8 + 4.3 + 4.12 + + + + + org.noear + solon-lib + 2.8.3 + provided + + + diff --git a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/SolonActionExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/SolonActionExecuteInterceptor.java new file mode 100644 index 0000000000..239e21cb80 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/SolonActionExecuteInterceptor.java @@ -0,0 +1,104 @@ +/* + * 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.solon; + +import lombok.extern.slf4j.Slf4j; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.util.StringUtil; +import org.noear.solon.core.NvMap; +import org.noear.solon.core.handle.Context; + +import java.lang.reflect.Method; + +@Slf4j +public class SolonActionExecuteInterceptor implements InstanceMethodsAroundInterceptorV2 { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInvocationContext context) throws Throwable { + Context ctx = (Context) allArguments[0]; + ContextCarrier contextCarrier = new ContextCarrier(); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + next.setHeadValue(ctx.header(next.getHeadKey())); + } + String operationName = ctx.method() + ":" + ctx.path(); + AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier); + span.setComponent(ComponentsDefine.SOLON_MVC); + SpanLayer.asHttp(span); + Tags.URL.set(span, ctx.url()); + Tags.HTTP.METHOD.set(span, ctx.method()); + if (SolonPluginConfig.Plugin.Solon.INCLUDE_HTTP_HEADERS != null && !SolonPluginConfig.Plugin.Solon.INCLUDE_HTTP_HEADERS.isEmpty()) { + NvMap includeHeaders = new NvMap(); + for (String header : SolonPluginConfig.Plugin.Solon.INCLUDE_HTTP_HEADERS) { + String value = ctx.header(header); + if (StringUtil.isNotBlank(value)) { + includeHeaders.put(header, value); + } + } + Tags.HTTP.HEADERS.set(span, includeHeaders.toString()); + } + if (SolonPluginConfig.Plugin.Solon.HTTP_BODY_LENGTH_THRESHOLD != 0) { + String body = ctx.body(); + if (StringUtil.isNotBlank(body)) { + if (SolonPluginConfig.Plugin.Solon.HTTP_BODY_LENGTH_THRESHOLD > 0 && body.length() > SolonPluginConfig.Plugin.Solon.HTTP_BODY_LENGTH_THRESHOLD) { + body = body.substring(0, SolonPluginConfig.Plugin.Solon.HTTP_BODY_LENGTH_THRESHOLD); + } + Tags.HTTP.BODY.set(span, body); + } + } + if (SolonPluginConfig.Plugin.Solon.HTTP_PARAMS_LENGTH_THRESHOLD != 0) { + String param = ctx.paramMap().toString(); + if (SolonPluginConfig.Plugin.Solon.HTTP_PARAMS_LENGTH_THRESHOLD > 0 && param.length() > SolonPluginConfig.Plugin.Solon.HTTP_PARAMS_LENGTH_THRESHOLD) { + param = param.substring(0, SolonPluginConfig.Plugin.Solon.HTTP_PARAMS_LENGTH_THRESHOLD); + } + Tags.HTTP.PARAMS.set(span, param); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret, MethodInvocationContext context) { + Context ctx = (Context) allArguments[0]; + Tags.HTTP_RESPONSE_STATUS_CODE.set(ContextManager.activeSpan(), ctx.status()); + if (ctx.errors != null && context.getContext() == null) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(ctx.errors); + } + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { + AbstractSpan activeSpan = ContextManager.activeSpan(); + activeSpan.errorOccurred(); + activeSpan.log(t); + context.setContext(true); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/SolonPluginConfig.java b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/SolonPluginConfig.java new file mode 100644 index 0000000000..63a3f3ba98 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/SolonPluginConfig.java @@ -0,0 +1,43 @@ +/* + * 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.solon; + +import org.apache.skywalking.apm.agent.core.boot.PluginConfig; + +import java.util.List; + +public class SolonPluginConfig { + public static class Plugin { + @PluginConfig(root = SolonPluginConfig.class) + public static class Solon { + /** + * Define the max length of collected HTTP parameters. The default value(=0) means not collecting. + */ + public static int HTTP_PARAMS_LENGTH_THRESHOLD = 0; + /** + * Define the max length of collected HTTP body. The default value(=0) means not collecting. + */ + public static int HTTP_BODY_LENGTH_THRESHOLD = 0; + /** + * It controls what header data should be collected, values must be in lower case, if empty, no header data will be collected. default is empty. + */ + public static List INCLUDE_HTTP_HEADERS ; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/define/SolonActionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/define/SolonActionInstrumentation.java new file mode 100644 index 0000000000..d41d15ed45 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/solon/define/SolonActionInstrumentation.java @@ -0,0 +1,66 @@ +/* + * 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.solon.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.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +public class SolonActionInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 { + + private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.solon.SolonActionExecuteInterceptor"; + + @Override + public ClassMatch enhanceClass() { + return NameMatch.byName("org.noear.solon.SolonApp"); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { + return new InstanceMethodsInterceptV2Point[] { + new InstanceMethodsInterceptV2Point() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("tryHandle"); + } + + @Override + public String getMethodsInterceptorV2() { + return INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..01e6af6f77 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/solon-2.x-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. + +solon-2.x=org.apache.skywalking.apm.plugin.solon.define.SolonActionInstrumentation \ No newline at end of file diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index 65b95a6fbd..06f5717de0 100755 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -320,3 +320,9 @@ plugin.nettyhttp.supported_content_types_prefix=${SW_PLUGIN_NETTYHTTP_SUPPORTED_ plugin.rocketmqclient.collect_message_keys=${SW_PLUGIN_ROCKETMQCLIENT_COLLECT_MESSAGE_KEYS:false} # If set to true, the tags of messages would be collected by the plugin for RocketMQ Java client. plugin.rocketmqclient.collect_message_tags=${SW_PLUGIN_ROCKETMQCLIENT_COLLECT_MESSAGE_TAGS:false} +# Define the max length of collected HTTP parameters. The default value(=0) means not collecting. +plugin.solon.http_params_length_threshold=${SW_PLUGIN_SOLON_HTTP_PARAMS_LENGTH_THRESHOLD:0} +# It controls what header data should be collected, values must be in lower case, if empty, no header data will be collected. default is empty. +plugin.solon.include_http_headers=${SW_PLUGIN_SOLON_INCLUDE_HTTP_HEADERS:} +# Define the max length of collected HTTP body. The default value(=0) means not collecting. +plugin.solon.http_body_length_threshold=${SW_PLUGIN_SOLON_HTTP_BODY_LENGTH_THRESHOLD:0} 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 d8c4d160bb..e15b3b1f00 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -177,3 +177,4 @@ - spring-webflux-6.x-webclient - activemq-artemis-jakarta-client-2.x - c3p0-0.9.x +- solon-2.x \ No newline at end of file diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 99bd79d37d..c91c25d4a2 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -26,6 +26,7 @@ metrics based on the tracing data. * [Grizzly](https://github.com/eclipse-ee4j/grizzly) 2.3.x -> 4.x * [WebSphere Liberty](https://github.com/OpenLiberty/open-liberty) 23.x * [Netty HTTP](https://github.com/netty/netty) 4.1.x (Optional²) + * [Solon](https://github.com/opensolon/solon) 2.7.x -> 2.8.x * HTTP Client * [Feign](https://github.com/OpenFeign/feign) 9.x * [Netflix Spring Cloud Feign](https://github.com/spring-cloud/spring-cloud-openfeign) 1.1.x -> 2.x diff --git a/docs/en/setup/service-agent/java-agent/configurations.md b/docs/en/setup/service-agent/java-agent/configurations.md index 4126407d18..83837d33b7 100644 --- a/docs/en/setup/service-agent/java-agent/configurations.md +++ b/docs/en/setup/service-agent/java-agent/configurations.md @@ -133,7 +133,10 @@ This is the properties list supported in `agent/config/agent.config`. | `plugin.nettyhttp.supported_content_types_prefix` | When `COLLECT_REQUEST_BODY` is enabled and content-type start with `HTTP_SUPPORTED_CONTENT_TYPES_PREFIX`, collect the body of the request , multiple paths should be separated by `,` | SW_PLUGIN_NETTY_HTTP_SUPPORTED_CONTENT_TYPES_PREFIX | `application/json,text/` | | `plugin.rocketmqclient.collect_message_keys` | If set to true, the keys of messages would be collected by the plugin for RocketMQ Java client. | `plugin.rocketmqclient.collect_message_tags` | If set to true, the tags of messages would be collected by the plugin for RocketMQ Java client. -| +| `plugin.solon.http_params_length_threshold` | Define the max length of collected HTTP parameters. The default value(=0) means not collecting. | SW_PLUGIN_SOLON_HTTP_PARAMS_LENGTH_THRESHOLD | `0` | +| `plugin.solon.include_http_headers` | It controls what header data should be collected, values must be in lower case, if empty, no header data will be collected. default is empty. | SW_PLUGIN_SOLON_INCLUDE_HTTP_HEADERS | ``(No header would be collected) | +| `plugin.solon.http_body_length_threshold` | Define the max length of collected HTTP body. The default value(=0) means not collecting. | SW_PLUGIN_SOLON_HTTP_BODY_LENGTH_THRESHOLD | `0` | + # Reset Collection/Map type configurations as empty collection. diff --git a/test/plugin/scenarios/solon-2.x-scenario/bin/startup.sh b/test/plugin/scenarios/solon-2.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..6cfc6ad702 --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-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} "-Dskywalking.plugin.solon.http_params_length_threshold=1024" "-Dskywalking.plugin.solon.include_http_headers=content_type,host" ${home}/../libs/solon-2.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/solon-2.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/solon-2.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..bca5273af9 --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-scenario/config/expectedData.yaml @@ -0,0 +1,99 @@ +# 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: solon-2.x-scenario + segmentSize: ge 2 + segments: + - segmentId: not null + spans: + - operationName: GET:/testcase/error + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 158 + isError: true + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: not null} + - {key: http.method, value: GET} + - {key: http.headers, value: not null} + - {key: http.params, value: not null} + - {key: http.status_code, value: '500'} + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: java.lang.RuntimeException} + - {key: message, value: this is Error} + - {key: stack, value: not null} + refs: + - {parentEndpoint: 'GET:/testcase/test', networkAddress: 'localhost:8082', + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: solon-2.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: H2/JDBC/PreparedStatement/executeQuery + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: not null + endTime: not null + componentId: 32 + isError: false + spanType: Exit + peer: localhost:-1 + skipAnalysis: false + tags: + - {key: db.type, value: H2} + - {key: db.instance, value: test} + - {key: db.statement, value: SELECT 1 = 1} + - operationName: /testcase/error + parentSpanId: 0 + spanId: 2 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 128 + isError: true + spanType: Exit + peer: localhost:8082 + skipAnalysis: false + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8082/testcase/error'} + - {key: http.status_code, value: '500'} + - operationName: GET:/testcase/test + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 158 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8082/testcase/test'} + - {key: http.method, value: GET} + - {key: http.headers, value: not null} + - {key: http.params, value: '{}'} + - {key: http.status_code, value: '200'} diff --git a/test/plugin/scenarios/solon-2.x-scenario/configuration.yml b/test/plugin/scenarios/solon-2.x-scenario/configuration.yml new file mode 100644 index 0000000000..33cd22a0dc --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-scenario/configuration.yml @@ -0,0 +1,20 @@ +# 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:8082/testcase/test +healthCheck: http://localhost:8082/testcase/healthCheck +startScript: ./bin/startup.sh diff --git a/test/plugin/scenarios/solon-2.x-scenario/pom.xml b/test/plugin/scenarios/solon-2.x-scenario/pom.xml new file mode 100644 index 0000000000..3b850fff6b --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-scenario/pom.xml @@ -0,0 +1,105 @@ + + + + 4.0.0 + + org.apache.skywalking + solon-2.x-scenario + jar + 5.0.0 + + skywalking-solon-2.x-scenario + + + UTF-8 + 2.8.3 + ${test.solon.version} + + + + + org.noear + solon-api + ${test.solon.version} + + + cn.hutool + hutool-http + 5.8.25 + + + com.h2database + h2 + 1.4.200 + + + + + solon-2.x-scenario + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.0 + + 1.8 + 1.8 + ${project.build.sourceEncoding} + + + + org.noear + solon-maven-plugin + 2.8.3 + test.apache.skywalking.apm.testcase.sc.solon.App + + + + package + + repackage + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + + diff --git a/test/plugin/scenarios/solon-2.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/solon-2.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..c408decc9d --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + ${project.build.directory} + ./libs + + solon-2.x-scenario.jar + + 0775 + + + diff --git a/test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/App.java b/test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/App.java new file mode 100644 index 0000000000..dafe2bf504 --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/App.java @@ -0,0 +1,29 @@ +/* + * 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.sc.solon; + +import org.noear.solon.Solon; +import org.noear.solon.annotation.SolonMain; + +@SolonMain +public class App { + + public static void main(String[] args) { + Solon.start(App.class, args); + } +} diff --git a/test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/controller/Controller.java b/test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/controller/Controller.java new file mode 100644 index 0000000000..dece4c9615 --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/controller/Controller.java @@ -0,0 +1,55 @@ +/* + * 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.sc.solon.controller; + +import cn.hutool.http.HttpRequest; +import org.noear.solon.annotation.Body; +import org.noear.solon.annotation.Get; +import org.noear.solon.annotation.Inject; +import org.noear.solon.annotation.Mapping; +import org.noear.solon.annotation.Path; +import test.apache.skywalking.apm.testcase.sc.solon.service.TestService; + +import java.sql.SQLException; + +@org.noear.solon.annotation.Controller +public class Controller { + + @Inject + private TestService testService; + + @Mapping("/testcase/healthCheck") + public String healthCheck() { + return "healthCheck"; + } + + @Get + @Mapping("/testcase/{test}") + public String hello(@Body String body, @Path("test") String test) throws SQLException { + testService.executeSQL(); + String body1 = HttpRequest.get("http://localhost:8082/testcase/error").execute().body(); + return "Hello World"; + } + + @Get + @Mapping("/testcase/error") + public String error() { + throw new RuntimeException("this is Error"); + } + +} diff --git a/test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/service/TestService.java b/test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/service/TestService.java new file mode 100644 index 0000000000..ed05be7667 --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/solon/service/TestService.java @@ -0,0 +1,43 @@ +/* + * 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.sc.solon.service; + +import org.noear.solon.annotation.Component; +import org.noear.solon.annotation.Init; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +@Component +public class TestService { + + private Connection connection; + + @Init + private void setUp() throws SQLException { + connection = DriverManager.getConnection("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", ""); + } + + public void executeSQL() throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement("SELECT 1 = 1"); + preparedStatement.executeQuery(); + } + +} diff --git a/test/plugin/scenarios/solon-2.x-scenario/src/main/resources/app.yml b/test/plugin/scenarios/solon-2.x-scenario/src/main/resources/app.yml new file mode 100644 index 0000000000..86f1a8ddc0 --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-scenario/src/main/resources/app.yml @@ -0,0 +1,18 @@ +# +# 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: 8082 \ No newline at end of file diff --git a/test/plugin/scenarios/solon-2.x-scenario/support-version.list b/test/plugin/scenarios/solon-2.x-scenario/support-version.list new file mode 100644 index 0000000000..7e5c2fd224 --- /dev/null +++ b/test/plugin/scenarios/solon-2.x-scenario/support-version.list @@ -0,0 +1,18 @@ +# 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. + +2.7.2 +2.8.3 \ No newline at end of file From 2e082176889e552268c41fe8dbb1444839ef865c Mon Sep 17 00:00:00 2001 From: w2dp Date: Mon, 1 Jul 2024 17:01:00 +0800 Subject: [PATCH 024/114] Fixed issues in the MySQL component where the executeBatch method could result in empty SQL statements . (#702) --- CHANGES.md | 1 + .../StatementExecuteMethodsInterceptor.java | 8 +++++-- ...tatementExecuteMethodsInterceptorTest.java | 21 ++++++++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f80f1f151b..623b5015f1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,6 +21,7 @@ Release Notes. * Fix the opentracing toolkit SPI config * Improve 4x performance of ContextManagerExtendService.createTraceContext() * Add a plugin that supports the Solon framework. +* Fixed issues in the MySQL component where the executeBatch method could result in empty SQL statements . All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptor.java index 8895e118a5..0c2f5047b9 100644 --- a/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/mysql-common/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptor.java @@ -28,6 +28,7 @@ import org.apache.skywalking.apm.plugin.jdbc.SqlBodyUtil; import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos; import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import org.apache.skywalking.apm.util.StringUtil; import java.lang.reflect.Method; @@ -52,14 +53,17 @@ public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); /** - * The first argument of all intercept method in `com.mysql.jdbc.StatementImpl` class is SQL, except the - * `executeBatch` method that the jdbc plugin need to trace, because of this method argument size is zero. + * Except for the `executeBatch` method, the first parameter of all enhanced methods in `com.mysql.jdbc.StatementImpl` is the SQL statement. + * Therefore, executeBatch will attempt to obtain the SQL from `cacheObject`. */ String sql = ""; if (allArguments.length > 0) { sql = (String) allArguments[0]; sql = SqlBodyUtil.limitSqlBodySize(sql); + } else if (StringUtil.isNotBlank(cacheObject.getSql())) { + sql = SqlBodyUtil.limitSqlBodySize(cacheObject.getSql()); } + Tags.DB_STATEMENT.set(span, sql); span.setComponent(connectInfo.getComponent()); diff --git a/apm-sniffer/apm-sdk-plugin/mysql-common/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mysql-common/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptorTest.java index e3ceaa6228..df2769b8cd 100644 --- a/apm-sniffer/apm-sdk-plugin/mysql-common/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/mysql-common/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mysql/StatementExecuteMethodsInterceptorTest.java @@ -72,7 +72,8 @@ public void setUp() { JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 2048; serviceMethodInterceptor = new StatementExecuteMethodsInterceptor(); - enhanceRequireCacheObject = new StatementEnhanceInfos(connectionInfo, "SELECT * FROM test", "CallableStatement"); + enhanceRequireCacheObject = new StatementEnhanceInfos(connectionInfo, SQL, "CallableStatement"); + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(enhanceRequireCacheObject); when(method.getName()).thenReturn("executeQuery"); when(connectionInfo.getComponent()).thenReturn(ComponentsDefine.H2_JDBC_DRIVER); @@ -81,6 +82,24 @@ public void setUp() { when(connectionInfo.getDatabasePeer()).thenReturn("localhost:3307"); } + @Test + public void testCreateDatabaseSpanWithNoMethodParamButWithCache() throws Throwable { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 2048; + + serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[0], null, null); + serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[0], null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment segment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(segment).size(), is(1)); + AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0); + SpanAssert.assertLayer(span, SpanLayer.DB); + assertThat(span.getOperationName(), is("H2/JDBC/CallableStatement/executeQuery")); + SpanAssert.assertTag(span, 0, "H2"); + SpanAssert.assertTag(span, 1, "test"); + SpanAssert.assertTag(span, 2, SQL); + } + @Test public void testCreateDatabaseSpan() throws Throwable { JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 2048; From 744eb1e5d822f8e3564914cde52881620b77de78 Mon Sep 17 00:00:00 2001 From: darkness-2nd <81127133+darkness-2nd@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:33:03 +0800 Subject: [PATCH 025/114] Support Kafka 3.7+ (#707) --- .dlc.json | 3 +- CHANGES.md | 2 +- .../Kafka37AsyncConsumerInstrumentation.java | 40 +++++++++++++++++++ .../Kafka37LegacyConsumerInstrumentation.java | 40 +++++++++++++++++++ .../src/main/resources/skywalking-plugin.def | 4 +- .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 2 +- .../kafka/controller/CaseController.java | 15 ++++++- .../kafka-scenario/support-version.list | 3 ++ 9 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/Kafka37AsyncConsumerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/Kafka37LegacyConsumerInstrumentation.java diff --git a/.dlc.json b/.dlc.json index 1ae0883a40..6a207d2c58 100644 --- a/.dlc.json +++ b/.dlc.json @@ -36,6 +36,7 @@ 200, 301, 302, - 401 + 401, + 403 ] } diff --git a/CHANGES.md b/CHANGES.md index 623b5015f1..d2ab11f4ee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,7 +22,7 @@ Release Notes. * Improve 4x performance of ContextManagerExtendService.createTraceContext() * Add a plugin that supports the Solon framework. * Fixed issues in the MySQL component where the executeBatch method could result in empty SQL statements . - +* Support kafka-clients-3.7.x intercept All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/Kafka37AsyncConsumerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/Kafka37AsyncConsumerInstrumentation.java new file mode 100644 index 0000000000..7c24a135ac --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/Kafka37AsyncConsumerInstrumentation.java @@ -0,0 +1,40 @@ +/* + * 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.kafka.define; + +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * For Kafka 3.7.x change + * + *
+ *  1. The method named pollForFetchs was removed from KafkaConsumer to AsyncKafkaConsumer and LegacyKafkaConsumer
+ *  2. Because of the enhance class was changed, so we should create new Instrumentation to intercept the method
+ * 
+ */ +public class Kafka37AsyncConsumerInstrumentation extends KafkaConsumerInstrumentation { + + private static final String ENHANCE_CLASS_37_ASYNC = "org.apache.kafka.clients.consumer.internals.AsyncKafkaConsumer"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS_37_ASYNC); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/Kafka37LegacyConsumerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/Kafka37LegacyConsumerInstrumentation.java new file mode 100644 index 0000000000..95f33bfe82 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/Kafka37LegacyConsumerInstrumentation.java @@ -0,0 +1,40 @@ +/* + * 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.kafka.define; + +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * For Kafka 3.7.x change + * + *
+ *  1. The method named pollForFetchs was removed from KafkaConsumer to AsyncKafkaConsumer and LegacyKafkaConsumer
+ *  2. Because of the enhance class was changed, so we should create new Instrumentation to intercept the method
+ * 
+ */ +public class Kafka37LegacyConsumerInstrumentation extends KafkaConsumerInstrumentation { + + private static final String ENHANCE_CLASS_37_LEGACY = "org.apache.kafka.clients.consumer.internals.LegacyKafkaConsumer"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS_37_LEGACY); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/resources/skywalking-plugin.def index d807aceefe..a85deb260b 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/resources/skywalking-plugin.def @@ -18,4 +18,6 @@ kafka-0.11.x/1.x/2.x=org.apache.skywalking.apm.plugin.kafka.define.CallbackInstr kafka-0.11.x/1.x/2.x=org.apache.skywalking.apm.plugin.kafka.define.KafkaConsumerInstrumentation kafka-0.11.x/1.x/2.x=org.apache.skywalking.apm.plugin.kafka.define.KafkaProducerInstrumentation kafka-0.11.x/1.x/2.x=org.apache.skywalking.apm.plugin.kafka.define.KafkaProducerMapInstrumentation -kafka-0.11.x/1.x/2.x=org.apache.skywalking.apm.plugin.kafka.define.KafkaTemplateCallbackInstrumentation \ No newline at end of file +kafka-0.11.x/1.x/2.x=org.apache.skywalking.apm.plugin.kafka.define.KafkaTemplateCallbackInstrumentation +kafka-3.7.x=org.apache.skywalking.apm.plugin.kafka.define.Kafka37AsyncConsumerInstrumentation +kafka-3.7.x=org.apache.skywalking.apm.plugin.kafka.define.Kafka37LegacyConsumerInstrumentation 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 e15b3b1f00..d2c07c5a41 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -54,6 +54,7 @@ - jetty-client-9.x - jetty-server-9.x - kafka-0.11.x/1.x/2.x +- kafka-3.7.x - kotlin-coroutine - lettuce-5.x - light4j diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index c91c25d4a2..cd7c02f78b 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -76,7 +76,7 @@ metrics based on the tracing data. * MQ * [RocketMQ](https://github.com/apache/rocketmq) 3.x-> 5.x * [RocketMQ-gRPC](http://github.com/apache/rocketmq-clients) 5.x - * [Kafka](http://kafka.apache.org) 0.11.0.0 -> 3.2.3 + * [Kafka](http://kafka.apache.org) 0.11.0.0 -> 3.7.1 * [Spring-Kafka](https://github.com/spring-projects/spring-kafka) Spring Kafka Consumer 1.3.x -> 2.3.x (2.0.x and 2.1.x not tested and not recommended by [the official document](https://spring.io/projects/spring-kafka)) * [ActiveMQ](https://github.com/apache/activemq) 5.10.0 -> 5.15.4 * [RabbitMQ](https://www.rabbitmq.com/) 3.x-> 5.x diff --git a/test/plugin/scenarios/kafka-scenario/src/main/java/test/apache/skywalking/apm/testcase/kafka/controller/CaseController.java b/test/plugin/scenarios/kafka-scenario/src/main/java/test/apache/skywalking/apm/testcase/kafka/controller/CaseController.java index ea8bb6e3c1..ee6458bdc1 100644 --- a/test/plugin/scenarios/kafka-scenario/src/main/java/test/apache/skywalking/apm/testcase/kafka/controller/CaseController.java +++ b/test/plugin/scenarios/kafka-scenario/src/main/java/test/apache/skywalking/apm/testcase/kafka/controller/CaseController.java @@ -24,6 +24,7 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import java.util.Collection; import java.util.regex.Pattern; import java.util.List; import java.util.ArrayList; @@ -32,10 +33,10 @@ import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.apache.kafka.clients.consumer.ConsumerRebalanceListener; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.clients.consumer.KafkaConsumer; -import org.apache.kafka.clients.consumer.internals.NoOpConsumerRebalanceListener; import org.apache.kafka.clients.producer.Callback; import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.Producer; @@ -270,7 +271,17 @@ public void run() { consumerProperties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); consumerProperties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); KafkaConsumer consumer = new KafkaConsumer<>(consumerProperties); - consumer.subscribe(topicPattern, new NoOpConsumerRebalanceListener()); + consumer.subscribe(topicPattern, new ConsumerRebalanceListener() { + @Override + public void onPartitionsRevoked(Collection collection) { + + } + + @Override + public void onPartitionsAssigned(Collection collection) { + + } + }); while (true) { if (pollAndInvoke(consumer)) break; } diff --git a/test/plugin/scenarios/kafka-scenario/support-version.list b/test/plugin/scenarios/kafka-scenario/support-version.list index 1ffc63cb11..6e83b29a43 100644 --- a/test/plugin/scenarios/kafka-scenario/support-version.list +++ b/test/plugin/scenarios/kafka-scenario/support-version.list @@ -28,3 +28,6 @@ 3.0.2 3.1.2 3.2.3 +3.6.0 +3.7.0 +3.7.1 From 92b09c9d79ac9c5e70afef767b797512b8f424df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Fri, 26 Jul 2024 06:49:38 +0800 Subject: [PATCH 026/114] Released 9.3.0 and start 9.4.0 (#710) * [maven-release-plugin] prepare release v9.3.0 * [maven-release-plugin] prepare for next development iteration * Create changes-9.3.0.md * Update CHANGES.md --- CHANGES.md | 23 ++------------- .../apm-toolkit-kafka/pom.xml | 2 +- .../apm-toolkit-log4j-1.x/pom.xml | 2 +- .../apm-toolkit-log4j-2.x/pom.xml | 2 +- .../apm-toolkit-logback-1.x/pom.xml | 2 +- .../apm-toolkit-meter/pom.xml | 2 +- .../apm-toolkit-micrometer-1.10/pom.xml | 2 +- .../apm-toolkit-micrometer-registry/pom.xml | 2 +- .../apm-toolkit-opentracing/pom.xml | 2 +- .../apm-toolkit-trace/pom.xml | 2 +- .../apm-toolkit-webflux/pom.xml | 2 +- apm-application-toolkit/pom.xml | 2 +- apm-commons/apm-datacarrier/pom.xml | 2 +- apm-commons/apm-util/pom.xml | 2 +- apm-commons/pom.xml | 2 +- apm-protocol/apm-network/pom.xml | 2 +- apm-protocol/pom.xml | 2 +- apm-sniffer/apm-agent-core/pom.xml | 2 +- apm-sniffer/apm-agent/pom.xml | 2 +- .../activemq-5.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/aerospike-plugin/pom.xml | 2 +- .../apm-armeria-0.84.x-plugin/pom.xml | 2 +- .../apm-armeria-0.85.x-plugin/pom.xml | 2 +- .../apm-armeria-1.0.x-plugin/pom.xml | 2 +- .../apm-armeria-plugins/pom.xml | 2 +- .../asynchttpclient-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/avro-plugin/pom.xml | 2 +- .../baidu-brpc-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/baidu-brpc-plugin/pom.xml | 2 +- .../apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/canal-1.x-plugin/pom.xml | 2 +- .../cassandra-java-driver-3.x-plugin/pom.xml | 2 +- .../clickhouse-0.3.1-plugin/pom.xml | 2 +- .../clickhouse-0.3.2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/cxf-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/dbcp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/druid-1.x-plugin/pom.xml | 2 +- .../dubbo-2.7.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml | 2 +- .../dubbo-3.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-3.x-plugin/pom.xml | 2 +- .../dubbo-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-plugin/pom.xml | 2 +- .../elastic-job-2.x-plugin/pom.xml | 2 +- .../elasticjob-3.x-plugin/pom.xml | 2 +- .../elasticsearch-5.x-plugin/pom.xml | 2 +- .../elasticsearch-6.x-plugin/pom.xml | 2 +- .../elasticsearch-7.x-plugin/pom.xml | 2 +- .../elasticsearch-common/pom.xml | 2 +- .../feign-default-http-9.x-plugin/pom.xml | 2 +- .../finagle-6.25.x-plugin/pom.xml | 2 +- .../graphql-12.x-15.x-plugin/pom.xml | 2 +- .../graphql-16plus-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-8.x-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/graphql-plugin/pom.xml | 2 +- .../grizzly-2.3.x-4.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/grpc-1.x-plugin/pom.xml | 2 +- .../guava-eventbus-plugin/pom.xml | 2 +- .../apm-sdk-plugin/h2-1.x-plugin/pom.xml | 2 +- .../hbase-1.x-2.x-plugin/pom.xml | 2 +- .../hikaricp-3.x-4.x-plugin/pom.xml | 2 +- .../httpClient-4.x-plugin/pom.xml | 2 +- .../httpasyncclient-4.x-plugin/pom.xml | 2 +- .../httpclient-3.x-plugin/pom.xml | 2 +- .../httpclient-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/httpclient-commons/pom.xml | 2 +- .../hutool-http-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/hutool-plugins/pom.xml | 2 +- .../apm-sdk-plugin/hystrix-1.x-plugin/pom.xml | 2 +- .../influxdb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jdbc-commons/pom.xml | 2 +- .../jedis-2.x-3.x-plugin/pom.xml | 2 +- .../jedis-plugins/jedis-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jedis-plugins/pom.xml | 2 +- .../apm-sdk-plugin/jersey-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jersey-3.x-plugin/pom.xml | 2 +- .../jetty-client-11.x-plugin/pom.xml | 2 +- .../jetty-client-9.0-plugin/pom.xml | 2 +- .../jetty-client-9.x-plugin/pom.xml | 2 +- .../jetty-server-11.x-plugin/pom.xml | 2 +- .../jetty-server-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jetty-plugin/pom.xml | 2 +- .../jetty-thread-pool-plugin/pom.xml | 2 +- .../jsonrpc4j-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/kafka-commons/pom.xml | 2 +- .../apm-sdk-plugin/kafka-plugin/pom.xml | 2 +- .../kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/lettuce-5.x-plugin/pom.xml | 2 +- .../light4j-plugins/light4j-plugin/pom.xml | 2 +- .../apm-sdk-plugin/light4j-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mariadb-2.x-plugin/pom.xml | 2 +- .../micronaut-http-client-plugin/pom.xml | 2 +- .../micronaut-http-server-plugin/pom.xml | 2 +- .../apm-sdk-plugin/micronaut-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/motan-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mssql-commons/pom.xml | 2 +- .../apm-sdk-plugin/mssql-jdbc-plugin/pom.xml | 2 +- .../mssql-jtds-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-6.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-common/pom.xml | 2 +- .../nats-2.14.x-2.15.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/neo4j-4.x-plugin/pom.xml | 2 +- .../netty-socketio-plugin/pom.xml | 2 +- .../nutz-plugins/http-1.x-plugin/pom.xml | 2 +- .../mvc-annotation-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/nutz-plugins/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-common/pom.xml | 2 +- .../apm-sdk-plugin/play-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-sdk-plugin/pom.xml | 2 +- .../postgresql-8.x-plugin/pom.xml | 2 +- .../pulsar-2.2-2.7-plugin/pom.xml | 2 +- .../pulsar-2.8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/pulsar-common/pom.xml | 2 +- .../apm-sdk-plugin/quasar-plugin/pom.xml | 2 +- .../apm-sdk-plugin/rabbitmq-plugin/pom.xml | 2 +- .../redisson-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/resteasy-plugin/pom.xml | 2 +- .../resteasy-server-3.x-plugin/pom.xml | 2 +- .../resteasy-server-4.x-plugin/pom.xml | 2 +- .../resteasy-server-6.x-plugin/pom.xml | 2 +- .../rocketMQ-3.x-plugin/pom.xml | 2 +- .../rocketMQ-4.x-plugin/pom.xml | 2 +- .../rocketMQ-5.x-plugin/pom.xml | 2 +- .../rocketMQ-client-java-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/servicecomb-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../shardingsphere-plugins/pom.xml | 2 +- .../sharding-sphere-3.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.0.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.1.0-plugin/pom.xml | 2 +- .../sharding-sphere-5.0.0-plugin/pom.xml | 2 +- .../apm-sdk-plugin/sofarpc-plugin/pom.xml | 2 +- .../apm-sdk-plugin/solon-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/solrj-7.x-plugin/pom.xml | 2 +- .../async-annotation-plugin/pom.xml | 2 +- .../concurrent-util-4.x-plugin/pom.xml | 2 +- .../spring-plugins/core-patch/pom.xml | 2 +- .../mvc-annotation-3.x-plugin/pom.xml | 2 +- .../mvc-annotation-4.x-plugin/pom.xml | 2 +- .../mvc-annotation-5.x-plugin/pom.xml | 2 +- .../mvc-annotation-commons/pom.xml | 2 +- .../apm-sdk-plugin/spring-plugins/pom.xml | 2 +- .../resttemplate-3.x-plugin/pom.xml | 2 +- .../resttemplate-4.x-plugin/pom.xml | 2 +- .../resttemplate-commons/pom.xml | 2 +- .../scheduled-annotation-plugin/pom.xml | 2 +- .../spring-cloud/netflix-plugins/pom.xml | 2 +- .../spring-cloud-feign-1.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-cloud/pom.xml | 2 +- .../spring-cloud-feign-2.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-commons/pom.xml | 2 +- .../spring-kafka-1.x-plugin/pom.xml | 2 +- .../spring-kafka-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../spymemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/struts2-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/thrift-plugin/pom.xml | 2 +- .../apm-sdk-plugin/tomcat-10x-plugin/pom.xml | 2 +- .../tomcat-7.x-8.x-plugin/pom.xml | 2 +- .../tomcat-thread-pool-plugin/pom.xml | 2 +- .../apm-sdk-plugin/undertow-plugins/pom.xml | 2 +- .../undertow-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/vertx-plugins/pom.xml | 2 +- .../vertx-core-3.x-plugin/pom.xml | 2 +- .../vertx-core-4.x-plugin/pom.xml | 2 +- .../websphere-liberty-23.x-plugin/pom.xml | 2 +- .../xmemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-test-tools/pom.xml | 2 +- .../apm-toolkit-kafka-activation/pom.xml | 2 +- .../apm-toolkit-log4j-1.x-activation/pom.xml | 2 +- .../apm-toolkit-log4j-2.x-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-logging-common/pom.xml | 2 +- .../apm-toolkit-meter-activation/pom.xml | 2 +- .../apm-toolkit-micrometer-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-trace-activation/pom.xml | 2 +- .../apm-toolkit-webflux-activation/pom.xml | 2 +- apm-sniffer/apm-toolkit-activation/pom.xml | 2 +- .../jdk-forkjoinpool-plugin/pom.xml | 2 +- .../bootstrap-plugins/jdk-http-plugin/pom.xml | 2 +- .../jdk-threading-plugin/pom.xml | 2 +- .../jdk-threadpool-plugin/pom.xml | 2 +- apm-sniffer/bootstrap-plugins/pom.xml | 2 +- apm-sniffer/bytebuddy-patch/pom.xml | 2 +- .../impala-jdbc-2.6.x-plugin/pom.xml | 2 +- apm-sniffer/expired-plugins/pom.xml | 2 +- .../customize-enhance-plugin/pom.xml | 2 +- .../ehcache-2.x-plugin/pom.xml | 2 +- .../fastjson-1.2.x-plugin/pom.xml | 2 +- .../gson-2.8.x-plugin/pom.xml | 2 +- .../guava-cache-plugin/pom.xml | 2 +- .../jackson-2.x-plugin/pom.xml | 2 +- .../kotlin-coroutine-plugin/pom.xml | 2 +- .../mybatis-3.x-plugin/pom.xml | 2 +- .../nacos-client-2.x-plugin/pom.xml | 2 +- .../netty-http-4.1.x-plugin/pom.xml | 2 +- .../mvc-annotation-6.x-plugin/pom.xml | 2 +- .../gateway-2.0.x-plugin/pom.xml | 2 +- .../gateway-2.1.x-plugin/pom.xml | 2 +- .../gateway-3.x-plugin/pom.xml | 2 +- .../gateway-4.x-plugin/pom.xml | 2 +- .../optional-spring-cloud/pom.xml | 2 +- .../optional-spring-plugins/pom.xml | 2 +- .../resttemplate-6.x-plugin/pom.xml | 2 +- .../spring-annotation-plugin/pom.xml | 2 +- .../spring-tx-plugin/pom.xml | 2 +- .../spring-webflux-5.x-plugin/pom.xml | 2 +- .../spring-webflux-6.x-plugin/pom.xml | 2 +- apm-sniffer/optional-plugins/pom.xml | 2 +- .../quartz-scheduler-2.x-plugin/pom.xml | 2 +- .../sentinel-1.x-plugin/pom.xml | 2 +- .../shenyu-2.4.x-plugin/pom.xml | 2 +- .../trace-ignore-plugin/pom.xml | 2 +- .../trace-sampler-cpu-policy-plugin/pom.xml | 2 +- .../zookeeper-3.4.x-plugin/pom.xml | 2 +- .../kafka-config-extension/pom.xml | 2 +- .../kafka-reporter-plugin/pom.xml | 2 +- apm-sniffer/optional-reporter-plugins/pom.xml | 2 +- apm-sniffer/pom.xml | 2 +- changes/changes-9.3.0.md | 28 +++++++++++++++++++ pom.xml | 2 +- 236 files changed, 265 insertions(+), 254 deletions(-) create mode 100644 changes/changes-9.3.0.md diff --git a/CHANGES.md b/CHANGES.md index d2ab11f4ee..22dea7bad8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,29 +2,12 @@ Changes by Version ================== Release Notes. -9.3.0 +9.4.0 ------------------ -* Remove `idleCount` tag in Alibaba Druid meter plugin. -* Fix NPE in handleMethodException method of apm-jdk-threadpool-plugin. -* Support for C3P0 connection pool tracing. -* Use a daemon thread to flush logs. -* Fix typos in `URLParser`. -* Add support for `Derby`/`Sybase`/`SQLite`/`DB2`/`OceanBase` jdbc url format in `URLParser`. -* Optimize spring-plugins:scheduled-annotation-plugin compatibility about Spring 6.1.x support. -* Add a forceIgnoring mechanism in a CROSS_THREAD scenario. -* Fix NPE in Redisson plugin since Redisson 3.20.0. -* Support for showing batch command details and ignoring PING commands in Redisson plugin. -* Fix peer value of Master-Slave mode in Redisson plugin. -* Support for tracing the callbacks of asynchronous methods in elasticsearch-6.x-plugin/elasticsearch-7.x-plugin. -* Fixed the invalid issue in the isInterface method in PluginFinder. -* Fix the opentracing toolkit SPI config -* Improve 4x performance of ContextManagerExtendService.createTraceContext() -* Add a plugin that supports the Solon framework. -* Fixed issues in the MySQL component where the executeBatch method could result in empty SQL statements . -* Support kafka-clients-3.7.x intercept -All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) ------------------ Find change logs of all versions [here](changes). diff --git a/apm-application-toolkit/apm-toolkit-kafka/pom.xml b/apm-application-toolkit/apm-toolkit-kafka/pom.xml index 6edc74c7fb..d6edf28b6c 100644 --- a/apm-application-toolkit/apm-toolkit-kafka/pom.xml +++ b/apm-application-toolkit/apm-toolkit-kafka/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml index 057ac5676d..f6f5121d89 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml index e334a37b0e..e60e68ed89 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml index 2484061d6e..1c14cfc123 100644 --- a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-meter/pom.xml b/apm-application-toolkit/apm-toolkit-meter/pom.xml index c8453f9f17..a5860a3f51 100644 --- a/apm-application-toolkit/apm-toolkit-meter/pom.xml +++ b/apm-application-toolkit/apm-toolkit-meter/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml index b9c1a09c78..908892f0d7 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml index 5554bbf8a0..e2ee0ea1ca 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml index 5bfe3f8f26..3261da8b71 100644 --- a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml +++ b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-trace/pom.xml b/apm-application-toolkit/apm-toolkit-trace/pom.xml index b942b7afb5..f1ae80be59 100644 --- a/apm-application-toolkit/apm-toolkit-trace/pom.xml +++ b/apm-application-toolkit/apm-toolkit-trace/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-webflux/pom.xml b/apm-application-toolkit/apm-toolkit-webflux/pom.xml index 3a74445896..b1a13f52e5 100644 --- a/apm-application-toolkit/apm-toolkit-webflux/pom.xml +++ b/apm-application-toolkit/apm-toolkit-webflux/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/pom.xml b/apm-application-toolkit/pom.xml index 03e7a72ec0..73586f919b 100644 --- a/apm-application-toolkit/pom.xml +++ b/apm-application-toolkit/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 apm-application-toolkit diff --git a/apm-commons/apm-datacarrier/pom.xml b/apm-commons/apm-datacarrier/pom.xml index 899bcb889c..781cfec5d6 100644 --- a/apm-commons/apm-datacarrier/pom.xml +++ b/apm-commons/apm-datacarrier/pom.xml @@ -21,7 +21,7 @@ java-agent-commons org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/apm-util/pom.xml b/apm-commons/apm-util/pom.xml index b87ce0fdd3..7fa74fac6b 100644 --- a/apm-commons/apm-util/pom.xml +++ b/apm-commons/apm-util/pom.xml @@ -20,7 +20,7 @@ java-agent-commons org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/pom.xml b/apm-commons/pom.xml index 210ef6205f..522ec3086d 100644 --- a/apm-commons/pom.xml +++ b/apm-commons/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/apm-network/pom.xml b/apm-protocol/apm-network/pom.xml index f7d68fbcbe..195286c43a 100644 --- a/apm-protocol/apm-network/pom.xml +++ b/apm-protocol/apm-network/pom.xml @@ -21,7 +21,7 @@ java-agent-protocol org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/pom.xml b/apm-protocol/pom.xml index b29b3b9732..47ffbfe637 100644 --- a/apm-protocol/pom.xml +++ b/apm-protocol/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index 2ea7df432e..8ba309156f 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-agent-core diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index d11eb7d06a..5f7246b372 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-agent diff --git a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml index 8420d03312..684cc8bf76 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml index 6527e2dae4..4fa869a203 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml index 554cd600c8..85734b3665 100644 --- a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml index 9bda76fd4d..8df069e81d 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml index b44db06e67..29653163a7 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml index 3423b90100..0b19011684 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml index 1ecdee4e30..677b9953d8 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml index 075c51cb44..be8e1e10d9 100644 --- a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml index 5e6d29aac1..4cbdd59f07 100644 --- a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml index 35c4df05a9..977b8d5fa4 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml index f5d447f483..ca29c17a63 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml index 3d61e4cc0d..9ed08a7919 100644 --- a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml index b7416bc262..6440a943a0 100644 --- a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml index be6fbca7ec..20e3580fc3 100644 --- a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml index b71127cd6d..8c749b4cc3 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml index 6e7edbe2ef..bfccb45b00 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml index 0f056f4135..618a7bc934 100644 --- a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml index f6326650e5..c97d28f835 100644 --- a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml index 10e1afb8f9..290abe63bf 100644 --- a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml index ee46e542ff..54f688dc68 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml index 8ff3bb504e..f8b7395ae4 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml index 3fbd5240e3..9e7a515ce4 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml index 1728372ca7..71d8e01916 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml index 326b3c0ca7..6c584299cf 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml index 1555484e02..52efdd6390 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml index 94bc082bf4..cfb502b8f7 100644 --- a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml index d82734c045..a2d47d0c11 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml index 6205465134..0e10a3c699 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml index 204b52615a..162d069a9b 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml index d8d15a0d32..29ca4de3b1 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml index 1658b62cce..4ae4ea02d3 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml index e641e9512f..ac3528c7e0 100644 --- a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml index cc875605fa..2743a90796 100644 --- a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml index b56a1905e3..288189e69b 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml index 7cd4ed7172..d514800ee5 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml index c9d0fa4de0..f0a274a768 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml index 39666ba3e1..f1f10b73ce 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml index dd0f22b3fd..b5fcb7965e 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml index 5c4f29668d..23d0caea0e 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml index 958782012c..faf700318e 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-grizzly-2.x-4.x-work-threadpool-plugin diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml index 76b32efb36..1d9b3fdbf5 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-grpc-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml index 31109f5f26..c6cba9b84d 100644 --- a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml index ef577b70b2..f4de4fa62b 100755 --- a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml index e852e6cb80..bc77540d04 100644 --- a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-hbase-1.x-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml index a48229f282..f9d9b2d48b 100644 --- a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml index 772529e458..ccaeccbe9a 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-httpClient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml index 87656a9dbc..84d552aee1 100644 --- a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-httpasyncclient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml index e03fcef53c..190ef1b0df 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-httpclient-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml index d205761cee..9375758907 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-httpclient-5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml index e0cdc80bbe..30e4f38ff2 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-httpclient-commons diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml index f2d0495cc8..cb83a4f056 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ hutool-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml index 3394b0092c..aab144f839 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml index b4ed0b93b3..bea536a191 100644 --- a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml index ab281eaeb1..4b3767a0dc 100644 --- a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml index a6485b4582..0f6be0acff 100755 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml index 310e07a400..49ec8c40cc 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking jedis-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml index 1f6cc9db71..35893a8c2d 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ jedis-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml index 56bf312da3..93809620f5 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT diff --git a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml index 0f56f34dbf..1d08051a7e 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml index 36070531c2..eba3b4768a 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml index cde6fd5449..2d3577a606 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml index 199bc45aac..ea620bb103 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml index 8e091d09b2..e4d2cf3890 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml index 2f0ae53188..7fae8c33d1 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml index 03f8740533..ad6d25acdd 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml index d939bf88b5..59ea20b3db 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT jetty-plugins diff --git a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml index 101dcaae14..e461d1cf3b 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml index 533e961137..b44f44d3d0 100644 --- a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml index bf86caceda..bd6687307d 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-kafka-commons diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml index c5e17d52ed..7ec88ebbc3 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml index 74ee2c3c55..6db9466b71 100644 --- a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml index ed057fe5ef..3835354ea5 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-lettuce-5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml index 722371d8b5..cc692737a5 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml @@ -20,7 +20,7 @@ light4j-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml index 5d738e3b5f..b3eaf724c3 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT light4j-plugins diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml index 05ab767ccb..4ef60ef291 100644 --- a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml index 30b35cca03..0ffd372cfd 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml index 6f3b7c80bd..e48c03c52e 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml index 931bc20085..a35c15c0e0 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml index 4fb80d5e87..2d4b0ec700 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml index 68c1ade2e2..c521caf896 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-mongodb-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml index 868f1d9ab7..504554f186 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-mongodb-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml index 51b3fec800..ee2b1dc842 100644 --- a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml index 6cbcb3a4af..c612a36766 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml index e8da306dd9..39812a801a 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml index be33212cbe..f55cc9c4e1 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml index babac7d15d..4356ae4288 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml index 932e2aadf6..ba7bd8dc18 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml index fd95d69452..371bbad8f8 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml index 4ce77ba866..7640bd37ef 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml index 8ec619ea33..2585e9370f 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml index 8cb025d1be..7603cb938c 100644 --- a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml index bd80a20010..039e28556f 100644 --- a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml index da79858c39..777579e6d9 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml index b9ba31e760..038c1b4871 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml index 669753f580..aa0cf71596 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT nutz-plugins diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml index 770d413b09..fea937cfad 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml index eca6ff770b..b709dab5d4 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml index ce9ce36b53..4127a432cf 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml index 3881fd2396..013ffdf693 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml index e5ce15cff8..617ffe7406 100644 --- a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-play-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index bc2aa1f68c..b62e8269e2 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking java-agent-sniffer - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-sdk-plugin diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml index 46da28a309..2a7c718929 100755 --- a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml index 27dbb81b6a..1b57fb9c45 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml index 7f219a6086..aaefac8f38 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml index ab1a87f751..256a1dc1cc 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml index a0a5219174..a42bb810bb 100644 --- a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-quasar-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml index a4ffebf7d3..9d0e0b0ffe 100644 --- a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml index 19f79cbc3e..c8a11445d4 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-redisson-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml index aca4e0a2e2..9c24d18dbe 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT resteasy-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml index 7f911f2507..69d1761dd1 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT resteasy-server-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml index 4590d8e2ec..a15a08e6e4 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT resteasy-server-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml index 1b91053387..0e13f993b9 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT resteasy-server-6.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml index 72feb352bf..933fd8465a 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml index 7b3c637a92..2c3c4cb46b 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml index 5669605bb4..bcda3ff1b0 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml index c48f2da760..208087afb8 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml index 9a64259d48..607b2e50bd 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml index 71b5934e03..5a9023f5a0 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ servicecomb-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml index 7f124736d2..ff5e8625db 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml index 41131a2b2d..120ef8335a 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml index 3493c95e09..e3fc5f69dc 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml index b86c520ac5..5b83c087ce 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml index 176dba0ace..2a147a76b3 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml index 5a6e57662a..0bcfc585a3 100644 --- a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml index ca4dc473d2..34efbc6d2e 100644 --- a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT solon-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml index 64a46cd10c..8ab65b23b9 100644 --- a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml index c0484a07f1..b056c8adb3 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml index 0c49963f86..f76e078491 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml index 5807a025ba..c46812fcd1 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml index dfab514b02..e06e754cd2 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml index 0d6d45e1e4..b63777a63e 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml index f74cf3733c..41d9d85f1f 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml @@ -19,7 +19,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml index eb71af642d..a4aa39a70a 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml index 64abfdb7eb..1325ebcb8d 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT spring-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml index 4814e20078..cda376e6d9 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml index 08789aa954..72fe157d21 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml index 4976c79954..bdfb781386 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml index 23a5790757..0953926c68 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml index 89283b1370..f79b0b7985 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT netflix-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml index d11a119602..7ab120108c 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking netflix-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-spring-cloud-feign-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml index 08afa3d3f0..345b39b97b 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT spring-cloud diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml index a9d0430b86..8f8da9a5ec 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-spring-cloud-feign-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml index 5e48bb5251..b0eca05cc1 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml index 3f06456a34..0b9af9a642 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-spring-kafka-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml index 9741509279..4714fb7076 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-spring-kafka-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml index 868bd94200..413b41440c 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml index 528735645b..49428bd872 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml index a44cd64c18..9630275ea3 100644 --- a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-spymemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml index b116ccd389..fa90818a41 100644 --- a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml index 9d8692028e..e3c9c5a399 100644 --- a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml index 48b7ce02ff..3581c999e1 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml index c881962896..cfcd3d7b94 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml index 6fc859269b..356f3ae1f2 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml index 85ad76522d..d1979611a1 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT undertow-plugins diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml index b5abe20db9..4a6b293848 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ undertow-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml index 9e500f59ae..06470ce5d3 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml index b5818b98f3..76e3334c3f 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT vertx-plugins diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml index e9c720d80f..d4b8889bd5 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml index 42a48a40e3..d2bed74c43 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml index a2ba27cf03..887fbb702e 100644 --- a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml index 841535f8db..6cac80505e 100644 --- a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-xmemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml index a008627a7a..66704f142c 100644 --- a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-test-tools/pom.xml b/apm-sniffer/apm-test-tools/pom.xml index db5fa5298b..26e56d7774 100644 --- a/apm-sniffer/apm-test-tools/pom.xml +++ b/apm-sniffer/apm-test-tools/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-test-tools diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml index 5c7df0c206..8a2d66f56f 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml index 1b937485b5..a8b14ecd3b 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml index a4d7f78bbe..36d099f5fd 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml index 9134874b44..a77fad6f98 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml index 85659cfb98..05d9223fe1 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml index 30a272ff2c..519a5c3360 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml index d63725b992..e8980c845c 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml index d0484207c1..a9695ba387 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml index 56a268c4a1..091c15950f 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml index f56c2edf8f..5826a56466 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/pom.xml index f597ebabea..29e360a6c0 100644 --- a/apm-sniffer/apm-toolkit-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml index 0f9790e758..94b80ea606 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml index a1bcb92708..6e3f0886b4 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml index 29efafb1ae..7754fc0800 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml index 91799d8558..035168e0d6 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml @@ -20,7 +20,7 @@ bootstrap-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/pom.xml b/apm-sniffer/bootstrap-plugins/pom.xml index bc540de6ab..5a12be422d 100644 --- a/apm-sniffer/bootstrap-plugins/pom.xml +++ b/apm-sniffer/bootstrap-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bytebuddy-patch/pom.xml b/apm-sniffer/bytebuddy-patch/pom.xml index e5ec1d0cda..3c351af416 100644 --- a/apm-sniffer/bytebuddy-patch/pom.xml +++ b/apm-sniffer/bytebuddy-patch/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking java-agent-sniffer - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml index 38b2880c74..8488cf4e05 100644 --- a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml +++ b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml @@ -24,7 +24,7 @@ org.apache.skywalking expired-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-impala-jdbc-2.6.x-plugin diff --git a/apm-sniffer/expired-plugins/pom.xml b/apm-sniffer/expired-plugins/pom.xml index 817506785a..5f991dde32 100644 --- a/apm-sniffer/expired-plugins/pom.xml +++ b/apm-sniffer/expired-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml index 2c9ee683f6..ac5116d0bd 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml index 02c5ad33f5..d5c5381557 100644 --- a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml index f0019fa5ec..42bffedf1d 100644 --- a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-fastjson-1.x-plugin diff --git a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml index 8211d2e4df..c45e4d70be 100644 --- a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-gson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml index 79cfd12796..f021f273dc 100644 --- a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-guava-cache-plugin diff --git a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml index 75279981da..3cd08b5c9f 100644 --- a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-jackson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml index 6c34690e6e..bf9ed9c729 100644 --- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-kotlin-coroutine-plugin diff --git a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml index b738e93ad5..67db73c337 100644 --- a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-mybatis-3.x-plugin diff --git a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml index 6da357f801..9d185c1b44 100644 --- a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml index a135366369..0776e16111 100644 --- a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml index ed3daad261..59826b659c 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml @@ -19,7 +19,7 @@ optional-spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml index c483e6b29d..3e1ccd7e94 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-spring-cloud-gateway-2.0.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml index 9973fe43dc..555c650198 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-spring-cloud-gateway-2.1.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml index dae580784f..139917052e 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml index 73ed729672..59f5bb76fb 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml index bec5510816..d28ac5a57a 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT optional-spring-cloud diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml index 6e599a881a..e4f16f60c9 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml index dc75494925..58284c10b3 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ optional-spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml index e4d9a96ddc..87669f820f 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml index f8c0c38b0e..14299642e3 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml index e85753da89..1338ef5105 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml index a9a8514fff..7350b5b8aa 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml index 590d2b4094..4a55525da8 100644 --- a/apm-sniffer/optional-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml index c79b83a730..ead3f06035 100644 --- a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-quartz-scheduler-2.x-plugin diff --git a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml index 7a936d292d..3d63d85ece 100644 --- a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml index 6cb94a441d..d4201cbbce 100644 --- a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml index 710c5df2da..ed86661634 100644 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml index c55bf77f12..e7a6318374 100644 --- a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml index 8f9166a80a..93de4d4018 100644 --- a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT apm-zookeeper-3.4.x-plugin diff --git a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml index 63c5e84eec..c583447e44 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml @@ -20,7 +20,7 @@ optional-reporter-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml index 9a752ab8e0..0f795f03a0 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml @@ -21,7 +21,7 @@ optional-reporter-plugins org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/pom.xml b/apm-sniffer/optional-reporter-plugins/pom.xml index 608e4171ee..4446e5b489 100644 --- a/apm-sniffer/optional-reporter-plugins/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/pom.xml b/apm-sniffer/pom.xml index 8f5d3c0c32..98cfaf4012 100644 --- a/apm-sniffer/pom.xml +++ b/apm-sniffer/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT 4.0.0 diff --git a/changes/changes-9.3.0.md b/changes/changes-9.3.0.md new file mode 100644 index 0000000000..304feb01ae --- /dev/null +++ b/changes/changes-9.3.0.md @@ -0,0 +1,28 @@ +Changes by Version +================== +Release Notes. + +9.3.0 +------------------ + +* Remove `idleCount` tag in Alibaba Druid meter plugin. +* Fix NPE in handleMethodException method of apm-jdk-threadpool-plugin. +* Support for C3P0 connection pool tracing. +* Use a daemon thread to flush logs. +* Fix typos in `URLParser`. +* Add support for `Derby`/`Sybase`/`SQLite`/`DB2`/`OceanBase` jdbc url format in `URLParser`. +* Optimize spring-plugins:scheduled-annotation-plugin compatibility about Spring 6.1.x support. +* Add a forceIgnoring mechanism in a CROSS_THREAD scenario. +* Fix NPE in Redisson plugin since Redisson 3.20.0. +* Support for showing batch command details and ignoring PING commands in Redisson plugin. +* Fix peer value of Master-Slave mode in Redisson plugin. +* Support for tracing the callbacks of asynchronous methods in elasticsearch-6.x-plugin/elasticsearch-7.x-plugin. +* Fixed the invalid issue in the isInterface method in PluginFinder. +* Fix the opentracing toolkit SPI config +* Improve 4x performance of ContextManagerExtendService.createTraceContext() +* Add a plugin that supports the Solon framework. +* Fixed issues in the MySQL component where the executeBatch method could result in empty SQL statements. +* Support kafka-clients-3.7.x. + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/213?closed=1) + diff --git a/pom.xml b/pom.xml index c6dca564f9..adac36458d 100755 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent - 9.3.0-SNAPSHOT + 9.4.0-SNAPSHOT org.apache From 24ec663a349df733c77bec792bc5ee81dc5632b7 Mon Sep 17 00:00:00 2001 From: "pg.yang" Date: Sat, 27 Jul 2024 12:36:04 +0800 Subject: [PATCH 027/114] Upgrade nats plugin to expand support to 2.16.5 (#711) --- .github/workflows/plugins-test.3.yaml | 2 +- CHANGES.md | 1 + .../pom.xml | 2 +- .../client/CreateDispatcherInterceptor.java | 0 .../nats/client/CreateSubInterceptor.java | 0 .../nats/client/DeliverReplyInterceptor.java | 0 .../apm/plugin/nats/client/NatsCommons.java | 0 ...onnectionWriterConstructorInterceptor.java | 0 .../NatsJetStreamConstructorInterceptor.java | 0 .../nats/client/NatsMessageInterceptor.java | 0 ...atsSubscriptionConstructorInterceptor.java | 0 .../SubscriptionNextMsgInterceptor.java | 0 .../nats/client/WriterQueueInterceptor.java | 0 .../WriterSendMessageBatchInterceptor.java | 0 .../AbstractWitnessInstrumentation.java | 43 +++++++++++++++++++ .../define/NatsConnectionInstrumentation.java | 5 +-- .../NatsConnectionWriterInstrumentation.java | 3 +- .../define/NatsJetStreamInstrumentation.java | 5 +-- .../define/NatsMessageInstrumentation.java | 3 +- .../NatsSubscriptionInstrumentation.java | 3 +- .../src/main/resources/skywalking-plugin.def | 10 ++--- apm-sniffer/apm-sdk-plugin/pom.xml | 2 +- .../service-agent/java-agent/Plugin-list.md | 4 +- .../java-agent/Supported-list.md | 2 +- .../bin/startup.sh | 2 +- .../config/expectedData.yaml | 0 .../configuration.yml | 0 .../pom.xml | 6 +-- .../src/main/assembly/assembly.xml | 2 +- .../apm/testcase/nats/client/Application.java | 0 .../client/controller/StartController.java | 0 .../client/publisher/JetStreamPublisher.java | 0 .../publisher/JetStreamPublisherFetcher.java | 0 .../client/publisher/NormalPublisher.java | 0 .../nats/client/publisher/Publisher.java | 0 .../client/publisher/ReqReplyPublisher.java | 0 .../nats/client/subscriber/Consumer.java | 0 .../subscriber/JetStreamFetcherConsumer.java | 0 .../subscriber/JetStreamHandlerConsumer.java | 0 .../client/subscriber/NextMsgConsumer.java | 0 .../client/subscriber/ReqReplyConsumer.java | 0 .../testcase/nats/client/work/StopSignal.java | 0 .../testcase/nats/client/work/StreamUtil.java | 0 .../nats/client/work/TrackedConnection.java | 0 .../nats/client/work/WorkBuilder.java | 0 .../support-version.list | 3 +- 46 files changed, 69 insertions(+), 29 deletions(-) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/pom.xml (96%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateDispatcherInterceptor.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateSubInterceptor.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/DeliverReplyInterceptor.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsCommons.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsConnectionWriterConstructorInterceptor.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsJetStreamConstructorInterceptor.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsMessageInterceptor.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsSubscriptionConstructorInterceptor.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/SubscriptionNextMsgInterceptor.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterQueueInterceptor.java (100%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterSendMessageBatchInterceptor.java (100%) create mode 100644 apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/AbstractWitnessInstrumentation.java rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionInstrumentation.java (94%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionWriterInstrumentation.java (95%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsJetStreamInstrumentation.java (94%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsMessageInstrumentation.java (93%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsSubscriptionInstrumentation.java (93%) rename apm-sniffer/apm-sdk-plugin/{nats-2.14.x-2.15.x-plugin => nats-2.14.x-2.16.5-plugin}/src/main/resources/skywalking-plugin.def (72%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/bin/startup.sh (94%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/config/expectedData.yaml (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/configuration.yml (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/pom.xml (96%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/assembly/assembly.xml (94%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/Application.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/controller/StartController.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisher.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisherFetcher.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/NormalPublisher.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/Publisher.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/ReqReplyPublisher.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/Consumer.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamFetcherConsumer.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamHandlerConsumer.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/NextMsgConsumer.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/ReqReplyConsumer.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StopSignal.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StreamUtil.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/TrackedConnection.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/WorkBuilder.java (100%) rename test/plugin/scenarios/{nats-2.14.x-2.15.x-scenario => nats-2.14.x-2.16.5-scenario}/support-version.list (98%) diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index 5960da690a..b6766b15a0 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -67,7 +67,7 @@ jobs: - vertx-web-3.6plus-scenario - mariadb-scenario - micronaut-http-scenario - - nats-2.14.x-2.15.x-scenario + - nats-2.14.x-2.16.5-scenario - quasar-scenario - baidu-brpc-scenario - baidu-brpc-3.x-scenario diff --git a/CHANGES.md b/CHANGES.md index 22dea7bad8..8a31625dc9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ Release Notes. 9.4.0 ------------------ +* Upgrade nats plugin to support 2.16.5 All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml similarity index 96% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml index 2585e9370f..843fc387d0 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml @@ -26,7 +26,7 @@ 4.0.0 - nats-2.14.x-2.15.x-plugin + nats-2.14.x-2.16.5-plugin jar diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateDispatcherInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateDispatcherInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateDispatcherInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateDispatcherInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateSubInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateSubInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateSubInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/CreateSubInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/DeliverReplyInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/DeliverReplyInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/DeliverReplyInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/DeliverReplyInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsCommons.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsCommons.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsCommons.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsCommons.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsConnectionWriterConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsConnectionWriterConstructorInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsConnectionWriterConstructorInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsConnectionWriterConstructorInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsJetStreamConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsJetStreamConstructorInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsJetStreamConstructorInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsJetStreamConstructorInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsMessageInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsMessageInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsMessageInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsMessageInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsSubscriptionConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsSubscriptionConstructorInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsSubscriptionConstructorInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/NatsSubscriptionConstructorInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/SubscriptionNextMsgInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/SubscriptionNextMsgInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/SubscriptionNextMsgInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/SubscriptionNextMsgInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterQueueInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterQueueInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterQueueInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterQueueInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterSendMessageBatchInterceptor.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterSendMessageBatchInterceptor.java similarity index 100% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterSendMessageBatchInterceptor.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/WriterSendMessageBatchInterceptor.java diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/AbstractWitnessInstrumentation.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/AbstractWitnessInstrumentation.java new file mode 100644 index 0000000000..1acf6e525e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/AbstractWitnessInstrumentation.java @@ -0,0 +1,43 @@ +/* + * 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.nats.client.define; + +import java.util.Collections; +import java.util.List; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +public abstract class AbstractWitnessInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + /* + * Currently, we only support 2.14.x-2.16.5, as there is no proper way and opportunity + * to change the message header and re-calculate the message length for 2.16.5+ yet. + * This method prevents users from applying this plugin to unsupported versions, + * which may cause unknown errors. + * For more information: https://github.com/apache/skywalking/discussions/11650 + */ + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + "io.nats.client.impl.NatsMessage", + named("calculateIfDirty") + )); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionInstrumentation.java similarity index 94% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionInstrumentation.java index 1822732b15..9b2d5087d7 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionInstrumentation.java @@ -21,14 +21,13 @@ 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.takesArguments; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; -public class NatsConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { +public class NatsConnectionInstrumentation extends AbstractWitnessInstrumentation { private static final String ENHANCE_CLASS = "io.nats.client.impl.NatsConnection"; @@ -82,4 +81,4 @@ public boolean isOverrideArgs() { } }; } -} \ No newline at end of file +} diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionWriterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionWriterInstrumentation.java similarity index 95% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionWriterInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionWriterInstrumentation.java index f3a315314f..b6e56ddc4a 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionWriterInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsConnectionWriterInstrumentation.java @@ -21,14 +21,13 @@ 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.takesArguments; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; -public class NatsConnectionWriterInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { +public class NatsConnectionWriterInstrumentation extends AbstractWitnessInstrumentation { private static final String ENHANCE_CLASS = "io.nats.client.impl.NatsConnectionWriter"; private static final String PUBLISH_INTERCEPTOR_CLASS_NAME = "org.apache.skywalking.apm.plugin.nats.client.WriterSendMessageBatchInterceptor"; diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsJetStreamInstrumentation.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsJetStreamInstrumentation.java similarity index 94% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsJetStreamInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsJetStreamInstrumentation.java index a635658c4a..cf940e7e39 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsJetStreamInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsJetStreamInstrumentation.java @@ -21,14 +21,13 @@ 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.takesArguments; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; -public class NatsJetStreamInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { +public class NatsJetStreamInstrumentation extends AbstractWitnessInstrumentation { private static final String ENHANCE_CLASS = "io.nats.client.impl.NatsJetStream"; private static final String CREATE_SUB_INTERCEPTOR = "org.apache.skywalking.apm.plugin.nats.client.CreateSubInterceptor"; @@ -78,4 +77,4 @@ public boolean isOverrideArgs() { }; } -} \ No newline at end of file +} diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsMessageInstrumentation.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsMessageInstrumentation.java similarity index 93% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsMessageInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsMessageInstrumentation.java index 79d061a396..95d229690b 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsMessageInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsMessageInstrumentation.java @@ -21,7 +21,6 @@ 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; @@ -35,7 +34,7 @@ * * BTW , ACK is done by publishing a message , So we needn't enhance ACK method */ -public class NatsMessageInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { +public class NatsMessageInstrumentation extends AbstractWitnessInstrumentation { private static final String ENHANCE_CLASS = "io.nats.client.impl.NatsMessage"; private static final String PUBLISH_INTERCEPTOR = "org.apache.skywalking.apm.plugin.nats.client.NatsMessageInterceptor"; diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsSubscriptionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsSubscriptionInstrumentation.java similarity index 93% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsSubscriptionInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsSubscriptionInstrumentation.java index a04433722a..62bc14b017 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsSubscriptionInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/java/org/apache/skywalking/apm/plugin/nats/client/define/NatsSubscriptionInstrumentation.java @@ -21,14 +21,13 @@ 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.takesArguments; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; -public class NatsSubscriptionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { +public class NatsSubscriptionInstrumentation extends AbstractWitnessInstrumentation { private static final String ENHANCE_CLASS = "io.nats.client.impl.NatsSubscription"; private static final String NEXT_MSG_INTERCEPTOR = "org.apache.skywalking.apm.plugin.nats.client.SubscriptionNextMsgInterceptor"; diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/resources/skywalking-plugin.def similarity index 72% rename from apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/resources/skywalking-plugin.def rename to apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/resources/skywalking-plugin.def index cc15654fcf..cbbf148d66 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.15.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/src/main/resources/skywalking-plugin.def @@ -14,8 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -nats-client-2.14.x-2.15.x=org.apache.skywalking.apm.plugin.nats.client.define.NatsMessageInstrumentation -nats-client-2.14.x-2.15.x=org.apache.skywalking.apm.plugin.nats.client.define.NatsConnectionInstrumentation -nats-client-2.14.x-2.15.x=org.apache.skywalking.apm.plugin.nats.client.define.NatsConnectionWriterInstrumentation -nats-client-2.14.x-2.15.x=org.apache.skywalking.apm.plugin.nats.client.define.NatsSubscriptionInstrumentation -nats-client-2.14.x-2.15.x=org.apache.skywalking.apm.plugin.nats.client.define.NatsJetStreamInstrumentation \ No newline at end of file +nats-client-2.14.x-2.16.5=org.apache.skywalking.apm.plugin.nats.client.define.NatsMessageInstrumentation +nats-client-2.14.x-2.16.5=org.apache.skywalking.apm.plugin.nats.client.define.NatsConnectionInstrumentation +nats-client-2.14.x-2.16.5=org.apache.skywalking.apm.plugin.nats.client.define.NatsConnectionWriterInstrumentation +nats-client-2.14.x-2.16.5=org.apache.skywalking.apm.plugin.nats.client.define.NatsSubscriptionInstrumentation +nats-client-2.14.x-2.16.5=org.apache.skywalking.apm.plugin.nats.client.define.NatsJetStreamInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index b62e8269e2..203fb664f7 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -123,7 +123,7 @@ guava-eventbus-plugin hutool-plugins micronaut-plugins - nats-2.14.x-2.15.x-plugin + nats-2.14.x-2.16.5-plugin jedis-plugins apm-armeria-plugins jetty-thread-pool-plugin 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 d2c07c5a41..2c7b51a6c3 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -162,7 +162,7 @@ - hutool-http-5.x - micronaut-http-client-3.2.x-3.6.x - micronaut-http-server-3.2.x-3.6.x -- nats-client-2.14.x-2.15.x +- nats-client-2.14.x-2.16.5 - impala-jdbc-2.6.x - jdk-forkjoinpool-plugin - jetty-thread-pool @@ -178,4 +178,4 @@ - spring-webflux-6.x-webclient - activemq-artemis-jakarta-client-2.x - c3p0-0.9.x -- solon-2.x \ No newline at end of file +- solon-2.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index cd7c02f78b..fe3bcd231d 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -81,7 +81,7 @@ metrics based on the tracing data. * [ActiveMQ](https://github.com/apache/activemq) 5.10.0 -> 5.15.4 * [RabbitMQ](https://www.rabbitmq.com/) 3.x-> 5.x * [Pulsar](http://pulsar.apache.org) 2.2.x -> 2.9.x - * [NATS](https://github.com/nats-io/nats.java) 2.14.x -> 2.15.x + * [NATS](https://github.com/nats-io/nats.java) 2.14.x -> 2.16.5 * [ActiveMQ-Artemis](https://github.com/apache/activemq) 2.30.0 -> 2.31.2 * Aliyun ONS 1.x (Optional¹) * NoSQL diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/bin/startup.sh b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/bin/startup.sh similarity index 94% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/bin/startup.sh rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/bin/startup.sh index d2237e1e87..ded2569231 100644 --- a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/bin/startup.sh +++ b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/bin/startup.sh @@ -21,4 +21,4 @@ home="$(cd "$(dirname $0)"; pwd)" java -jar ${agent_opts} -Dserver.port=8080 \ -Dskywalking.agent.service_name=scenario-8080- \ -Dnats.server=nats-server \ - ${home}/../libs/nats-2.14.x-2.15.x-scenario.jar & \ No newline at end of file + ${home}/../libs/nats-2.14.x-2.16.5-scenario.jar & diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/config/expectedData.yaml similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/config/expectedData.yaml rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/config/expectedData.yaml diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/configuration.yml b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/configuration.yml similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/configuration.yml rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/configuration.yml diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/pom.xml b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/pom.xml similarity index 96% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/pom.xml rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/pom.xml index 5234f29e9a..3fdcfa2857 100644 --- a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/pom.xml +++ b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/pom.xml @@ -21,7 +21,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> org.apache.skywalking.apm.testcase - nats-2.14.x-2.15.x-scenario + nats-2.14.x-2.16.5-scenario 1.0.0 jar @@ -75,7 +75,7 @@
- nats-2.14.x-2.15.x-scenario + nats-2.14.x-2.16.5-scenario org.springframework.boot @@ -112,4 +112,4 @@ - \ No newline at end of file + diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/assembly/assembly.xml similarity index 94% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/assembly/assembly.xml rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/assembly/assembly.xml index 098c888d81..dd2cf1d4f5 100644 --- a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/assembly/assembly.xml +++ b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/assembly/assembly.xml @@ -33,7 +33,7 @@ - ${project.build.directory}/nats-2.14.x-2.15.x-scenario.jar + ${project.build.directory}/nats-2.14.x-2.16.5-scenario.jar ./libs 0775 diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/Application.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/Application.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/Application.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/Application.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/controller/StartController.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/controller/StartController.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/controller/StartController.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/controller/StartController.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisher.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisher.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisher.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisher.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisherFetcher.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisherFetcher.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisherFetcher.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/JetStreamPublisherFetcher.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/NormalPublisher.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/NormalPublisher.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/NormalPublisher.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/NormalPublisher.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/Publisher.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/Publisher.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/Publisher.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/Publisher.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/ReqReplyPublisher.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/ReqReplyPublisher.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/ReqReplyPublisher.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/publisher/ReqReplyPublisher.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/Consumer.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/Consumer.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/Consumer.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/Consumer.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamFetcherConsumer.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamFetcherConsumer.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamFetcherConsumer.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamFetcherConsumer.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamHandlerConsumer.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamHandlerConsumer.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamHandlerConsumer.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/JetStreamHandlerConsumer.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/NextMsgConsumer.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/NextMsgConsumer.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/NextMsgConsumer.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/NextMsgConsumer.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/ReqReplyConsumer.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/ReqReplyConsumer.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/ReqReplyConsumer.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/subscriber/ReqReplyConsumer.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StopSignal.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StopSignal.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StopSignal.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StopSignal.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StreamUtil.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StreamUtil.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StreamUtil.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/StreamUtil.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/TrackedConnection.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/TrackedConnection.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/TrackedConnection.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/TrackedConnection.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/WorkBuilder.java b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/WorkBuilder.java similarity index 100% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/WorkBuilder.java rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/src/main/java/org/apache/skywalking/apm/testcase/nats/client/work/WorkBuilder.java diff --git a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/support-version.list b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/support-version.list similarity index 98% rename from test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/support-version.list rename to test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/support-version.list index 9798fc44d8..25a0bd9d45 100644 --- a/test/plugin/scenarios/nats-2.14.x-2.15.x-scenario/support-version.list +++ b/test/plugin/scenarios/nats-2.14.x-2.16.5-scenario/support-version.list @@ -14,5 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. +2.16.5 2.15.6 -2.14.2 \ No newline at end of file +2.14.2 From aa24777193f7b4e77aea24302b14f42eb140eb16 Mon Sep 17 00:00:00 2001 From: Wan Kai Date: Mon, 5 Aug 2024 22:27:43 +0800 Subject: [PATCH 028/114] Bump up skywalking-infra-e2e to work around GHA removing `docker-compose` v1. (#713) --- .github/workflows/e2e.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index ad1536c3d9..99059989a0 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -60,6 +60,6 @@ jobs: with: go-version: '1.18' - name: Run E2E Tests - uses: apache/skywalking-infra-e2e@c1558dba921a36320f9fdc3d774b66592243589d + uses: apache/skywalking-infra-e2e@cf589b4a0b9f8e6f436f78e9cfd94a1ee5494180 with: e2e-file: ${{ matrix.case.path }} From 75364241659c28e64557a3edffd53b9a8ae46188 Mon Sep 17 00:00:00 2001 From: weixiang1862 <652048614@qq.com> Date: Sun, 15 Sep 2024 18:04:09 +0800 Subject: [PATCH 029/114] Add agent self-observability. (#716) --- .github/actions/build/action.yml | 4 +- .github/actions/run/action.yml | 6 +- .github/workflows/plugins-test.0.yaml | 1 + .github/workflows/publish-docker.yaml | 4 +- CHANGES.md | 1 + .../agent/core/context/ContextManager.java | 2 + .../context/ContextManagerExtendService.java | 6 + .../core/context/IgnoredTracerContext.java | 2 + .../agent/core/context/TracingContext.java | 8 +- .../AbstractClassEnhancePluginDefine.java | 17 ++ .../agent/core/plugin/PluginBootstrap.java | 1 + .../bootstrap/BootstrapInstrumentBoost.java | 49 +++-- .../template/ConstructorInterTemplate.java | 14 ++ .../template/InstanceMethodInterTemplate.java | 20 ++ ...ceMethodInterWithOverrideArgsTemplate.java | 20 ++ .../template/StaticMethodInterTemplate.java | 21 +++ ...icMethodInterWithOverrideArgsTemplate.java | 21 +++ .../v2/InstanceMethodInterV2Template.java | 19 ++ ...MethodInterV2WithOverrideArgsTemplate.java | 20 ++ .../v2/StaticMethodInterV2Template.java | 21 +++ ...MethodInterV2WithOverrideArgsTemplate.java | 21 +++ .../enhance/BootstrapInterRuntimeAssist.java | 14 ++ .../enhance/ClassEnhancePluginDefine.java | 10 +- .../interceptor/enhance/ConstructorInter.java | 13 +- .../interceptor/enhance/InstMethodsInter.java | 19 +- .../InstMethodsInterWithOverrideArgs.java | 18 +- .../enhance/StaticMethodsInter.java | 19 +- .../StaticMethodsInterWithOverrideArgs.java | 20 +- .../v2/ClassEnhancePluginDefineV2.java | 10 +- .../enhance/v2/InstMethodsInterV2.java | 19 +- .../InstMethodsInterV2WithOverrideArgs.java | 19 +- .../enhance/v2/StaticMethodsInterV2.java | 19 +- .../StaticMethodsInterV2WithOverrideArgs.java | 19 +- .../apm/agent/core/so11y/AgentSo11y.java | 153 +++++++++++++++ .../so11y/bootstrap/BootstrapPluginSo11y.java | 25 +++ .../bootstrap/BootstrapPluginSo11yBridge.java | 46 +++++ .../java-agent/Agent-self-observability.md | 16 ++ .../service-agent/java-agent/Plugin-test.md | 2 +- docs/menu.yml | 6 +- .../resources/compose-start-script.template | 6 +- .../resources/container-start-script.template | 5 + .../agent-so11y-scenario/bin/startup.sh | 21 +++ .../config/expectedData.yaml | 177 ++++++++++++++++++ .../agent-so11y-scenario/configuration.yml | 25 +++ .../scenarios/agent-so11y-scenario/pom.xml | 128 +++++++++++++ .../src/main/assembly/assembly.xml | 41 ++++ .../apm/testcase/h2/Application.java | 30 +++ .../h2/controller/CaseController.java | 76 ++++++++ .../testcase/h2/controller/SQLExecutor.java | 75 ++++++++ .../src/main/resources/application.yaml | 23 +++ .../src/main/resources/log4j2.xml | 30 +++ .../agent-so11y-scenario/support-version.list | 17 ++ .../config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- .../h2-scenario/config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- .../config/expectedData.yaml | 2 +- 64 files changed, 1340 insertions(+), 63 deletions(-) create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/bootstrap/BootstrapPluginSo11y.java create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/bootstrap/BootstrapPluginSo11yBridge.java create mode 100644 docs/en/setup/service-agent/java-agent/Agent-self-observability.md create mode 100644 test/plugin/scenarios/agent-so11y-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/agent-so11y-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/agent-so11y-scenario/configuration.yml create mode 100644 test/plugin/scenarios/agent-so11y-scenario/pom.xml create mode 100644 test/plugin/scenarios/agent-so11y-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/Application.java create mode 100644 test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/controller/CaseController.java create mode 100644 test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/controller/SQLExecutor.java create mode 100644 test/plugin/scenarios/agent-so11y-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/agent-so11y-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/agent-so11y-scenario/support-version.list diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 2b63165d0d..f233bda2e4 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -56,7 +56,7 @@ runs: ./mvnw -q --batch-mode clean package -Dmaven.test.skip || \ ./mvnw -q --batch-mode clean package -Dmaven.test.skip echo "::endgroup::" - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 name: Upload Agent with: name: skywalking-agent @@ -89,7 +89,7 @@ runs: docker save -o test-containers/skywalking-agent-test-jvm-1.0.0.tgz skywalking/agent-test-jvm:1.0.0 docker save -o test-containers/skywalking-agent-test-tomcat-1.0.0.tgz skywalking/agent-test-tomcat:1.0.0 echo "::endgroup::" - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 name: Upload Test Containers with: name: test-tools diff --git a/.github/actions/run/action.yml b/.github/actions/run/action.yml index 02fdb8503c..c0d5ba1172 100644 --- a/.github/actions/run/action.yml +++ b/.github/actions/run/action.yml @@ -25,11 +25,11 @@ inputs: runs: using: "composite" steps: - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4 with: name: skywalking-agent path: skywalking-agent - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4 with: name: test-tools - name: Load Test Containers @@ -53,7 +53,7 @@ runs: echo "::group::Run Plugin Test ${{ inputs.test_case }}" bash test/plugin/run.sh ${{ inputs.test_case }} echo "::endgroup::" - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 name: Upload Agent if: always() with: diff --git a/.github/workflows/plugins-test.0.yaml b/.github/workflows/plugins-test.0.yaml index 57cec68cf8..19127048b5 100644 --- a/.github/workflows/plugins-test.0.yaml +++ b/.github/workflows/plugins-test.0.yaml @@ -53,6 +53,7 @@ jobs: matrix: case: - activemq-scenario + - agent-so11y-scenario - apm-toolkit-trace-scenario - apm-toolkit-tracer-scenario - armeria-0.96minus-scenario diff --git a/.github/workflows/publish-docker.yaml b/.github/workflows/publish-docker.yaml index be696af980..704c05ad86 100644 --- a/.github/workflows/publish-docker.yaml +++ b/.github/workflows/publish-docker.yaml @@ -47,7 +47,7 @@ jobs: java-version: 17 - name: Build Agent run: make build - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v4 name: Upload Agent with: name: skywalking-agent @@ -71,7 +71,7 @@ jobs: - uses: actions/checkout@v2 with: submodules: true - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v4 with: name: skywalking-agent path: skywalking-agent diff --git a/CHANGES.md b/CHANGES.md index 8a31625dc9..f2534d9be3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Release Notes. ------------------ * Upgrade nats plugin to support 2.16.5 +* Add agent self-observability. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java index fe90d979cf..1da79e9cce 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManager.java @@ -26,6 +26,7 @@ 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.agent.core.sampling.SamplingService; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; import org.apache.skywalking.apm.util.StringUtil; import static org.apache.skywalking.apm.agent.core.conf.Config.Agent.OPERATION_NAME_THRESHOLD; @@ -52,6 +53,7 @@ private static AbstractTracerContext getOrCreate(String operationName, boolean f if (LOGGER.isDebugEnable()) { LOGGER.debug("No operation name, ignore this trace."); } + AgentSo11y.measureTracingContextCreation(forceSampling, true); context = new IgnoredTracerContext(); } else { if (EXTEND_SERVICE == null) { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java index 49faebdc0c..560d57c660 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/ContextManagerExtendService.java @@ -33,6 +33,7 @@ import org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager; import org.apache.skywalking.apm.agent.core.remote.GRPCChannelStatus; import org.apache.skywalking.apm.agent.core.sampling.SamplingService; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; import org.apache.skywalking.apm.util.StringUtil; @DefaultImplementor @@ -81,17 +82,22 @@ public AbstractTracerContext createTraceContext(String operationName, boolean fo * Don't trace anything if the backend is not available. */ if (!Config.Agent.KEEP_TRACING && GRPCChannelStatus.DISCONNECT.equals(status)) { + AgentSo11y.measureTracingContextCreation(forceSampling, true); return new IgnoredTracerContext(); } int suffixIdx = operationName.lastIndexOf("."); if (suffixIdx > -1 && ignoreSuffixSet.contains(operationName.substring(suffixIdx))) { + AgentSo11y.measureTracingContextCreation(forceSampling, true); context = new IgnoredTracerContext(); } else { SamplingService samplingService = ServiceManager.INSTANCE.findService(SamplingService.class); if (forceSampling || samplingService.trySampling(operationName)) { + AgentSo11y.measureTracingContextCreation(forceSampling, false); context = new TracingContext(operationName, spanLimitWatcher); } else { + AgentSo11y.measureTracingContextCreation(false, true); + AgentSo11y.measureLeakedTracingContext(true); context = new IgnoredTracerContext(); } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java index b91258ea6a..8bf57ee064 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/IgnoredTracerContext.java @@ -23,6 +23,7 @@ import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.NoopSpan; import org.apache.skywalking.apm.agent.core.profile.ProfileStatusContext; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; /** * The IgnoredTracerContext represent a context should be ignored. So it just maintains the stack with an @@ -116,6 +117,7 @@ public AbstractSpan activeSpan() { public boolean stopSpan(AbstractSpan span) { stackDepth--; if (stackDepth == 0) { + AgentSo11y.measureTracingContextCompletion(true); ListenerManager.notifyFinish(this); } return stackDepth == 0; diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java index cffdbb2d38..cc1faa9af7 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/TracingContext.java @@ -43,6 +43,7 @@ import org.apache.skywalking.apm.agent.core.logging.api.LogManager; import org.apache.skywalking.apm.agent.core.profile.ProfileStatusContext; import org.apache.skywalking.apm.agent.core.profile.ProfileTaskExecutionService; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; import org.apache.skywalking.apm.util.StringUtil; import static org.apache.skywalking.apm.agent.core.conf.Config.Agent.CLUSTER; @@ -460,7 +461,12 @@ private void finish() { } if (isFinishedInMainThread && (!isRunningInAsyncMode || asyncSpanCounter == 0)) { - TraceSegment finishedSegment = segment.finish(isLimitMechanismWorking()); + boolean limitMechanismWorking = isLimitMechanismWorking(); + if (limitMechanismWorking) { + AgentSo11y.measureLeakedTracingContext(false); + } + AgentSo11y.measureTracingContextCompletion(false); + TraceSegment finishedSegment = segment.finish(limitMechanismWorking); TracingContext.ListenerManager.notifyFinish(finishedSegment); running = false; } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java index 949f8d5813..c53e54f0fa 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java @@ -43,6 +43,10 @@ public abstract class AbstractClassEnhancePluginDefine { private static final ILog LOGGER = LogManager.getLogger(AbstractClassEnhancePluginDefine.class); + /** + * plugin name defined in skywalking-plugin.def + */ + private String pluginName; /** * New field name. */ @@ -199,4 +203,17 @@ public boolean isBootstrapInstrumentation() { * @return collections of {@link InstanceMethodsInterceptV2Point} */ public abstract StaticMethodsInterceptV2Point[] getStaticMethodsInterceptV2Points(); + + /** + * plugin name should be set after create PluginDefine instance + * + * @param pluginName key defined in skywalking-plugin.def + */ + protected void setPluginName(final String pluginName) { + this.pluginName = pluginName; + } + + public String getPluginName() { + return pluginName; + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginBootstrap.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginBootstrap.java index 7d54eebd73..75c9edc6e0 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginBootstrap.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginBootstrap.java @@ -65,6 +65,7 @@ public List loadPlugins() throws AgentPackageN LOGGER.debug("loading plugin class {}.", pluginDefine.getDefineClass()); AbstractClassEnhancePluginDefine plugin = (AbstractClassEnhancePluginDefine) Class.forName(pluginDefine.getDefineClass(), true, AgentClassLoader .getDefault()).newInstance(); + plugin.setPluginName(pluginDefine.getName()); plugins.add(plugin); } catch (Throwable t) { LOGGER.error(t, "load plugin [{}] failure.", pluginDefine.getDefineClass()); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/BootstrapInstrumentBoost.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/BootstrapInstrumentBoost.java index 523340a401..f5875a7616 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/BootstrapInstrumentBoost.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/BootstrapInstrumentBoost.java @@ -71,6 +71,9 @@ public class BootstrapInstrumentBoost { "org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2", "org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.StaticMethodsAroundInterceptorV2", "org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext", + + //SO11Y + "org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y" }; private static String INSTANCE_METHOD_DELEGATE_TEMPLATE = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.InstanceMethodInterTemplate"; @@ -162,11 +165,14 @@ private static boolean prepareJREInstrumentation(PluginFinder pluginFinder, for (InstanceMethodsInterceptPoint point : define.getInstanceMethodsInterceptPoints()) { if (point.isOverrideArgs()) { generateDelegator( - classesTypeMap, typePool, INSTANCE_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point - .getMethodsInterceptor()); + classesTypeMap, typePool, define.getPluginName(), + INSTANCE_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point.getMethodsInterceptor() + ); } else { generateDelegator( - classesTypeMap, typePool, INSTANCE_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor()); + classesTypeMap, typePool, define.getPluginName(), + INSTANCE_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor() + ); } } } @@ -174,7 +180,9 @@ private static boolean prepareJREInstrumentation(PluginFinder pluginFinder, if (Objects.nonNull(define.getConstructorsInterceptPoints())) { for (ConstructorInterceptPoint point : define.getConstructorsInterceptPoints()) { generateDelegator( - classesTypeMap, typePool, CONSTRUCTOR_DELEGATE_TEMPLATE, point.getConstructorInterceptor()); + classesTypeMap, typePool, define.getPluginName(), + CONSTRUCTOR_DELEGATE_TEMPLATE, point.getConstructorInterceptor() + ); } } @@ -182,11 +190,14 @@ private static boolean prepareJREInstrumentation(PluginFinder pluginFinder, for (StaticMethodsInterceptPoint point : define.getStaticMethodsInterceptPoints()) { if (point.isOverrideArgs()) { generateDelegator( - classesTypeMap, typePool, STATIC_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point - .getMethodsInterceptor()); + classesTypeMap, typePool, define.getPluginName(), + STATIC_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point.getMethodsInterceptor() + ); } else { generateDelegator( - classesTypeMap, typePool, STATIC_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor()); + classesTypeMap, typePool, define.getPluginName(), + STATIC_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor() + ); } } } @@ -202,14 +213,14 @@ private static boolean prepareJREInstrumentationV2(PluginFinder pluginFinder, if (Objects.nonNull(define.getInstanceMethodsInterceptV2Points())) { for (InstanceMethodsInterceptV2Point point : define.getInstanceMethodsInterceptV2Points()) { if (point.isOverrideArgs()) { - generateDelegator(classesTypeMap, typePool, - INSTANCE_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, - point.getMethodsInterceptorV2() + generateDelegator( + classesTypeMap, typePool, define.getPluginName(), + INSTANCE_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point.getMethodsInterceptorV2() ); } else { generateDelegator( - classesTypeMap, typePool, INSTANCE_METHOD_V2_DELEGATE_TEMPLATE, - point.getMethodsInterceptorV2() + classesTypeMap, typePool, define.getPluginName(), + INSTANCE_METHOD_V2_DELEGATE_TEMPLATE, point.getMethodsInterceptorV2() ); } } @@ -218,14 +229,14 @@ private static boolean prepareJREInstrumentationV2(PluginFinder pluginFinder, if (Objects.nonNull(define.getStaticMethodsInterceptV2Points())) { for (StaticMethodsInterceptV2Point point : define.getStaticMethodsInterceptV2Points()) { if (point.isOverrideArgs()) { - generateDelegator(classesTypeMap, typePool, - STATIC_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, - point.getMethodsInterceptorV2() + generateDelegator( + classesTypeMap, typePool, define.getPluginName(), + STATIC_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point.getMethodsInterceptorV2() ); } else { generateDelegator( - classesTypeMap, typePool, STATIC_METHOD_V2_DELEGATE_TEMPLATE, - point.getMethodsInterceptorV2() + classesTypeMap, typePool, define.getPluginName(), + STATIC_METHOD_V2_DELEGATE_TEMPLATE, point.getMethodsInterceptorV2() ); } } @@ -245,7 +256,7 @@ private static boolean prepareJREInstrumentationV2(PluginFinder pluginFinder, * pre-defined in SkyWalking agent core. */ private static void generateDelegator(Map classesTypeMap, TypePool typePool, - String templateClassName, String methodsInterceptor) { + String pluginName, String templateClassName, String methodsInterceptor) { String internalInterceptorName = internalDelegate(methodsInterceptor); try { TypeDescription templateTypeDescription = typePool.describe(templateClassName).resolve(); @@ -253,6 +264,8 @@ private static void generateDelegator(Map classesTypeMap, TypePo DynamicType.Unloaded interceptorType = new ByteBuddy().redefine(templateTypeDescription, ClassFileLocator.ForClassLoader .of(BootstrapInstrumentBoost.class.getClassLoader())) .name(internalInterceptorName) + .field(named("PLUGIN_NAME")) + .value(pluginName) .field(named("TARGET_INTERCEPTOR")) .value(methodsInterceptor) .make(); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/ConstructorInterTemplate.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/ConstructorInterTemplate.java index 756d03f299..06b7e8132e 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/ConstructorInterTemplate.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/ConstructorInterTemplate.java @@ -25,6 +25,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * --------CLASS TEMPLATE--------- @@ -37,6 +38,12 @@ * This class wouldn't be loaded in real env. This is a class template for dynamic class generation. */ public class ConstructorInterTemplate { + + private static final String INTERCEPTOR_TYPE = "constructor"; + /** + * This field is never set in the template, but has value in the runtime. + */ + private static String PLUGIN_NAME; /** * This field is never set in the template, but has value in the runtime. */ @@ -44,6 +51,7 @@ public class ConstructorInterTemplate { private static InstanceConstructorInterceptor INTERCEPTOR; private static IBootstrapLog LOGGER; + private static BootstrapPluginSo11y PLUGIN_SO11Y; /** * Intercept the target constructor. @@ -53,6 +61,8 @@ public class ConstructorInterTemplate { */ @RuntimeType public static void intercept(@This Object obj, @AllArguments Object[] allArguments) { + long interceptorTimeCost = 0L; + long startTime = System.nanoTime(); try { prepare(); @@ -64,7 +74,10 @@ public static void intercept(@This Object obj, @AllArguments Object[] allArgumen INTERCEPTOR.onConstruct(targetObject, allArguments); } catch (Throwable t) { LOGGER.error("ConstructorInter failure.", t); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTime; + PLUGIN_SO11Y.duration(interceptorTimeCost); } /** @@ -79,6 +92,7 @@ private static void prepare() { if (logger != null) { LOGGER = logger; + PLUGIN_SO11Y = BootstrapInterRuntimeAssist.getSO11Y(loader); INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER); } } else { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/InstanceMethodInterTemplate.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/InstanceMethodInterTemplate.java index ef70a5722b..62a0c8fac9 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/InstanceMethodInterTemplate.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/InstanceMethodInterTemplate.java @@ -30,6 +30,7 @@ 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.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * --------CLASS TEMPLATE--------- @@ -42,6 +43,12 @@ * This class wouldn't be loaded in real env. This is a class template for dynamic class generation. */ public class InstanceMethodInterTemplate { + + private static final String INTERCEPTOR_TYPE = "inst"; + /** + * This field is never set in the template, but has value in the runtime. + */ + private static String PLUGIN_NAME; /** * This field is never set in the template, but has value in the runtime. */ @@ -49,6 +56,7 @@ public class InstanceMethodInterTemplate { private static InstanceMethodsAroundInterceptor INTERCEPTOR; private static IBootstrapLog LOGGER; + private static BootstrapPluginSo11y PLUGIN_SO11Y; /** * Intercept the target instance method. @@ -68,6 +76,8 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum prepare(); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInterceptResult result = new MethodInterceptResult(); try { if (INTERCEPTOR != null) { @@ -77,7 +87,9 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -87,6 +99,7 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum ret = zuper.call(); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { if (INTERCEPTOR != null) { INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t); @@ -95,9 +108,12 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { if (INTERCEPTOR != null) { ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret); @@ -106,8 +122,11 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + PLUGIN_SO11Y.duration(interceptorTimeCost); return ret; } @@ -124,6 +143,7 @@ private static void prepare() { if (logger != null) { LOGGER = logger; + PLUGIN_SO11Y = BootstrapInterRuntimeAssist.getSO11Y(loader); INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER); } } else { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/InstanceMethodInterWithOverrideArgsTemplate.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/InstanceMethodInterWithOverrideArgsTemplate.java index 1ba0464de0..16053055d3 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/InstanceMethodInterWithOverrideArgsTemplate.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/InstanceMethodInterWithOverrideArgsTemplate.java @@ -30,6 +30,7 @@ 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.agent.core.plugin.interceptor.enhance.OverrideCallable; +import org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * --------CLASS TEMPLATE--------- @@ -42,6 +43,12 @@ * This class wouldn't be loaded in real env. This is a class template for dynamic class generation. */ public class InstanceMethodInterWithOverrideArgsTemplate { + + private static final String INTERCEPTOR_TYPE = "inst"; + /** + * This field is never set in the template, but has value in the runtime. + */ + private static String PLUGIN_NAME; /** * This field is never set in the template, but has value in the runtime. */ @@ -49,6 +56,7 @@ public class InstanceMethodInterWithOverrideArgsTemplate { private static InstanceMethodsAroundInterceptor INTERCEPTOR; private static IBootstrapLog LOGGER; + private static BootstrapPluginSo11y PLUGIN_SO11Y; /** * Intercept the target instance method. @@ -68,6 +76,8 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum prepare(); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInterceptResult result = new MethodInterceptResult(); try { if (INTERCEPTOR != null) { @@ -77,7 +87,9 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -87,6 +99,7 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum ret = zuper.call(allArguments); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { if (INTERCEPTOR != null) { INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t); @@ -95,9 +108,12 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { if (INTERCEPTOR != null) { ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret); @@ -106,8 +122,11 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + PLUGIN_SO11Y.duration(interceptorTimeCost); return ret; } @@ -124,6 +143,7 @@ private static void prepare() { if (logger != null) { LOGGER = logger; + PLUGIN_SO11Y = BootstrapInterRuntimeAssist.getSO11Y(loader); INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER); } } else { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/StaticMethodInterTemplate.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/StaticMethodInterTemplate.java index a4caf96528..e32b1fc554 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/StaticMethodInterTemplate.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/StaticMethodInterTemplate.java @@ -28,6 +28,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * --------CLASS TEMPLATE--------- @@ -40,6 +41,12 @@ * This class wouldn't be loaded in real env. This is a class template for dynamic class generation. */ public class StaticMethodInterTemplate { + + private static final String INTERCEPTOR_TYPE = "static"; + /** + * This field is never set in the template, but has value in the runtime. + */ + private static String PLUGIN_NAME; /** * This field is never set in the template, but has value in the runtime. */ @@ -47,6 +54,7 @@ public class StaticMethodInterTemplate { private static StaticMethodsAroundInterceptor INTERCEPTOR; private static IBootstrapLog LOGGER; + private static BootstrapPluginSo11y PLUGIN_SO11Y; /** * Intercept the target static method. @@ -64,6 +72,8 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al @SuperCall Callable zuper) throws Throwable { prepare(); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInterceptResult result = new MethodInterceptResult(); try { if (INTERCEPTOR != null) { @@ -71,7 +81,9 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al } } catch (Throwable t) { LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -81,23 +93,31 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al ret = zuper.call(); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { if (INTERCEPTOR != null) { INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t); } } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { if (INTERCEPTOR != null) { ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret); } } catch (Throwable t) { LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + PLUGIN_SO11Y.duration(interceptorTimeCost); + return ret; } @@ -113,6 +133,7 @@ private static void prepare() { if (logger != null) { LOGGER = logger; + PLUGIN_SO11Y = BootstrapInterRuntimeAssist.getSO11Y(loader); INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER); } } else { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/StaticMethodInterWithOverrideArgsTemplate.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/StaticMethodInterWithOverrideArgsTemplate.java index 6dd7ac0b00..c182878148 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/StaticMethodInterWithOverrideArgsTemplate.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/StaticMethodInterWithOverrideArgsTemplate.java @@ -28,6 +28,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * --------CLASS TEMPLATE--------- @@ -40,6 +41,12 @@ * This class wouldn't be loaded in real env. This is a class template for dynamic class generation. */ public class StaticMethodInterWithOverrideArgsTemplate { + + private static final String INTERCEPTOR_TYPE = "static"; + /** + * This field is never set in the template, but has value in the runtime. + */ + private static String PLUGIN_NAME; /** * This field is never set in the template, but has value in the runtime. */ @@ -47,6 +54,7 @@ public class StaticMethodInterWithOverrideArgsTemplate { private static StaticMethodsAroundInterceptor INTERCEPTOR; private static IBootstrapLog LOGGER; + private static BootstrapPluginSo11y PLUGIN_SO11Y; /** * Intercept the target static method. @@ -64,6 +72,8 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al @Morph OverrideCallable zuper) throws Throwable { prepare(); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInterceptResult result = new MethodInterceptResult(); try { if (INTERCEPTOR != null) { @@ -71,7 +81,9 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al } } catch (Throwable t) { LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -81,23 +93,31 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al ret = zuper.call(allArguments); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { if (INTERCEPTOR != null) { INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t); } } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { if (INTERCEPTOR != null) { ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret); } } catch (Throwable t) { LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + PLUGIN_SO11Y.duration(interceptorTimeCost); + return ret; } @@ -113,6 +133,7 @@ private static void prepare() { if (logger != null) { LOGGER = logger; + PLUGIN_SO11Y = BootstrapInterRuntimeAssist.getSO11Y(loader); INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER); } } else { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/InstanceMethodInterV2Template.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/InstanceMethodInterV2Template.java index 88be482f5f..92be67f5f8 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/InstanceMethodInterV2Template.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/InstanceMethodInterV2Template.java @@ -29,12 +29,18 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext; +import org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * This class wouldn't be loaded in real env. This is a class template for dynamic class generation. */ public class InstanceMethodInterV2Template { + private static final String INTERCEPTOR_TYPE = "inst"; + /** + * This field is never set in the template, but has value in the runtime. + */ + private static String PLUGIN_NAME; /** * This field is never set in the template, but has value in the runtime. */ @@ -42,6 +48,7 @@ public class InstanceMethodInterV2Template { private static InstanceMethodsAroundInterceptorV2 INTERCEPTOR; private static IBootstrapLog LOGGER; + private static BootstrapPluginSo11y PLUGIN_SO11Y; /** * Intercept the target instance method. @@ -61,6 +68,8 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum prepare(); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInvocationContext context = new MethodInvocationContext(); try { if (INTERCEPTOR != null) { @@ -70,7 +79,9 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -80,6 +91,7 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum ret = zuper.call(); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { if (INTERCEPTOR != null) { INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context); @@ -88,9 +100,12 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { if (INTERCEPTOR != null) { ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context); @@ -99,8 +114,11 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + PLUGIN_SO11Y.duration(interceptorTimeCost); return ret; } @@ -117,6 +135,7 @@ private static void prepare() { if (logger != null) { LOGGER = logger; + PLUGIN_SO11Y = BootstrapInterRuntimeAssist.getSO11Y(loader); INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER); } } else { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/InstanceMethodInterV2WithOverrideArgsTemplate.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/InstanceMethodInterV2WithOverrideArgsTemplate.java index 83fc8a9711..b027f086d3 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/InstanceMethodInterV2WithOverrideArgsTemplate.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/InstanceMethodInterV2WithOverrideArgsTemplate.java @@ -30,11 +30,18 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext; +import org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * This class wouldn't be loaded in real env. This is a class template for dynamic class generation. */ public class InstanceMethodInterV2WithOverrideArgsTemplate { + + private static final String INTERCEPTOR_TYPE = "inst"; + /** + * This field is never set in the template, but has value in the runtime. + */ + private static String PLUGIN_NAME; /** * This field is never set in the template, but has value in the runtime. */ @@ -42,6 +49,7 @@ public class InstanceMethodInterV2WithOverrideArgsTemplate { private static InstanceMethodsAroundInterceptorV2 INTERCEPTOR; private static IBootstrapLog LOGGER; + private static BootstrapPluginSo11y PLUGIN_SO11Y; /** * Intercept the target instance method. @@ -61,6 +69,8 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum prepare(); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInvocationContext context = new MethodInvocationContext(); try { if (INTERCEPTOR != null) { @@ -70,7 +80,9 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -80,6 +92,7 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum ret = zuper.call(allArguments); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { if (INTERCEPTOR != null) { INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context); @@ -88,9 +101,12 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { if (INTERCEPTOR != null) { ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context); @@ -99,8 +115,11 @@ public static Object intercept(@This Object obj, @AllArguments Object[] allArgum if (LOGGER != null) { LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName()); } + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + PLUGIN_SO11Y.duration(interceptorTimeCost); return ret; } @@ -117,6 +136,7 @@ private static void prepare() { if (logger != null) { LOGGER = logger; + PLUGIN_SO11Y = BootstrapInterRuntimeAssist.getSO11Y(loader); INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER); } } else { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/StaticMethodInterV2Template.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/StaticMethodInterV2Template.java index 74cfb1e26a..4541716c2f 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/StaticMethodInterV2Template.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/StaticMethodInterV2Template.java @@ -28,11 +28,18 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist; 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 org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * This class wouldn't be loaded in real env. This is a class template for dynamic class generation. */ public class StaticMethodInterV2Template { + + private static final String INTERCEPTOR_TYPE = "static"; + /** + * This field is never set in the template, but has value in the runtime. + */ + private static String PLUGIN_NAME; /** * This field is never set in the template, but has value in the runtime. */ @@ -40,6 +47,7 @@ public class StaticMethodInterV2Template { private static StaticMethodsAroundInterceptorV2 INTERCEPTOR; private static IBootstrapLog LOGGER; + private static BootstrapPluginSo11y PLUGIN_SO11Y; /** * Intercept the target static method. @@ -57,6 +65,8 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al @SuperCall Callable zuper) throws Throwable { prepare(); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInvocationContext context = new MethodInvocationContext(); try { if (INTERCEPTOR != null) { @@ -64,7 +74,9 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al } } catch (Throwable t) { LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -74,23 +86,31 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al ret = zuper.call(); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { if (INTERCEPTOR != null) { INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context); } } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { if (INTERCEPTOR != null) { ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context); } } catch (Throwable t) { LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + PLUGIN_SO11Y.duration(interceptorTimeCost); + return ret; } @@ -106,6 +126,7 @@ private static void prepare() { if (logger != null) { LOGGER = logger; + PLUGIN_SO11Y = BootstrapInterRuntimeAssist.getSO11Y(loader); INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER); } } else { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/StaticMethodInterV2WithOverrideArgsTemplate.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/StaticMethodInterV2WithOverrideArgsTemplate.java index 09607882d7..9297f36582 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/StaticMethodInterV2WithOverrideArgsTemplate.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/bootstrap/template/v2/StaticMethodInterV2WithOverrideArgsTemplate.java @@ -28,11 +28,18 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable; 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 org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * This class wouldn't be loaded in real env. This is a class template for dynamic class generation. */ public class StaticMethodInterV2WithOverrideArgsTemplate { + + private static final String INTERCEPTOR_TYPE = "static"; + /** + * This field is never set in the template, but has value in the runtime. + */ + private static String PLUGIN_NAME; /** * This field is never set in the template, but has value in the runtime. */ @@ -40,6 +47,7 @@ public class StaticMethodInterV2WithOverrideArgsTemplate { private static StaticMethodsAroundInterceptorV2 INTERCEPTOR; private static IBootstrapLog LOGGER; + private static BootstrapPluginSo11y PLUGIN_SO11Y; /** * Intercept the target static method. @@ -57,6 +65,8 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al @Morph OverrideCallable zuper) throws Throwable { prepare(); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInvocationContext context = new MethodInvocationContext(); try { if (INTERCEPTOR != null) { @@ -64,7 +74,9 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al } } catch (Throwable t) { LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -74,23 +86,31 @@ public static Object intercept(@Origin Class clazz, @AllArguments Object[] al ret = zuper.call(allArguments); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { if (INTERCEPTOR != null) { INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context); } } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { if (INTERCEPTOR != null) { ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context); } } catch (Throwable t) { LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage()); + PLUGIN_SO11Y.error(PLUGIN_NAME, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + PLUGIN_SO11Y.duration(interceptorTimeCost); + return ret; } @@ -106,6 +126,7 @@ private static void prepare() { if (logger != null) { LOGGER = logger; + PLUGIN_SO11Y = BootstrapInterRuntimeAssist.getSO11Y(loader); INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER); } } else { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/BootstrapInterRuntimeAssist.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/BootstrapInterRuntimeAssist.java index f667667a3e..9289391ccb 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/BootstrapInterRuntimeAssist.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/BootstrapInterRuntimeAssist.java @@ -22,6 +22,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import org.apache.skywalking.apm.agent.core.plugin.bootstrap.IBootstrapLog; +import org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11y; /** * This assist help all bootstrap class core interceptor. @@ -29,6 +30,8 @@ public class BootstrapInterRuntimeAssist { private static final String AGENT_CLASSLOADER_DEFAULT = "org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader"; private static final String DEFAULT_AGENT_CLASSLOADER_INSTANCE = "DEFAULT_LOADER"; + private static final String SO11Y_BRIDGE_CLASS = "org.apache.skywalking.apm.agent.core.so11y.bootstrap.BootstrapPluginSo11yBridge"; + private static final String SO11Y_BRIDGE_GET_SO11Y_METHOD = "getSo11y"; private static final String LOG_MANAGER_CLASS = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.BootstrapPluginLogBridge"; private static final String LOG_MANAGER_GET_LOGGER_METHOD = "getLogger"; private static final PrintStream OUT = System.out; @@ -62,6 +65,17 @@ public static IBootstrapLog getLogger(ClassLoader defaultAgentClassLoader, Strin } } + public static BootstrapPluginSo11y getSO11Y(ClassLoader defaultAgentClassLoader) { + try { + Class logManagerClass = Class.forName(SO11Y_BRIDGE_CLASS, true, defaultAgentClassLoader); + Method getLogger = logManagerClass.getMethod(SO11Y_BRIDGE_GET_SO11Y_METHOD); + return (BootstrapPluginSo11y) getLogger.invoke(null); + } catch (Exception e) { + e.printStackTrace(OUT); + return null; + } + } + public static T createInterceptor(ClassLoader defaultAgentClassLoader, String className, IBootstrapLog log) { try { Class interceptor = Class.forName(className, true, defaultAgentClassLoader); diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java index e1a1fa4261..f38ddfc5a8 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java @@ -121,7 +121,7 @@ protected DynamicType.Builder enhanceInstance(TypeDescription typeDescription } else { newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()) .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration() - .to(new ConstructorInter(constructorInterceptPoint + .to(new ConstructorInter(getPluginName(), constructorInterceptPoint .getConstructorInterceptor(), classLoader), delegateNamingResolver.resolve(constructorInterceptPoint)))); } } @@ -150,7 +150,7 @@ protected DynamicType.Builder enhanceInstance(TypeDescription typeDescription newClassBuilder = newClassBuilder.method(junction) .intercept(MethodDelegation.withDefaultConfiguration() .withBinders(Morph.Binder.install(OverrideCallable.class)) - .to(new InstMethodsInterWithOverrideArgs(interceptor, classLoader), delegateNamingResolver.resolve(instanceMethodsInterceptPoint))); + .to(new InstMethodsInterWithOverrideArgs(getPluginName(), interceptor, classLoader), delegateNamingResolver.resolve(instanceMethodsInterceptPoint))); } } else { if (isBootstrapInstrumentation()) { @@ -160,7 +160,7 @@ protected DynamicType.Builder enhanceInstance(TypeDescription typeDescription } else { newClassBuilder = newClassBuilder.method(junction) .intercept(MethodDelegation.withDefaultConfiguration() - .to(new InstMethodsInter(interceptor, classLoader), delegateNamingResolver.resolve(instanceMethodsInterceptPoint))); + .to(new InstMethodsInter(getPluginName(), interceptor, classLoader), delegateNamingResolver.resolve(instanceMethodsInterceptPoint))); } } } @@ -202,7 +202,7 @@ protected DynamicType.Builder enhanceClass(TypeDescription typeDescription, D newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher())) .intercept(MethodDelegation.withDefaultConfiguration() .withBinders(Morph.Binder.install(OverrideCallable.class)) - .to(new StaticMethodsInterWithOverrideArgs(interceptor), delegateNamingResolver.resolve(staticMethodsInterceptPoint))); + .to(new StaticMethodsInterWithOverrideArgs(getPluginName(), interceptor), delegateNamingResolver.resolve(staticMethodsInterceptPoint))); } } else { if (isBootstrapInstrumentation()) { @@ -212,7 +212,7 @@ protected DynamicType.Builder enhanceClass(TypeDescription typeDescription, D } else { newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher())) .intercept(MethodDelegation.withDefaultConfiguration() - .to(new StaticMethodsInter(interceptor), delegateNamingResolver.resolve(staticMethodsInterceptPoint))); + .to(new StaticMethodsInter(getPluginName(), interceptor), delegateNamingResolver.resolve(staticMethodsInterceptPoint))); } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ConstructorInter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ConstructorInter.java index 8a057df259..3a1063da03 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ConstructorInter.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ConstructorInter.java @@ -25,6 +25,7 @@ import org.apache.skywalking.apm.agent.core.plugin.PluginException; import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader; import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; /** * The actual byte-buddy's interceptor to intercept constructor methods. In this class, it provides a bridge between @@ -33,6 +34,9 @@ public class ConstructorInter { private static final ILog LOGGER = LogManager.getLogger(ConstructorInter.class); + private static final String INTERCEPTOR_TYPE = "constructor"; + + private String pluginName; /** * An {@link InstanceConstructorInterceptor} This name should only stay in {@link String}, the real {@link Class} * type will trigger classloader failure. If you want to know more, please check on books about Classloader or @@ -43,7 +47,8 @@ public class ConstructorInter { /** * @param constructorInterceptorClassName class full name. */ - public ConstructorInter(String constructorInterceptorClassName, ClassLoader classLoader) throws PluginException { + public ConstructorInter(String pluginName, String constructorInterceptorClassName, ClassLoader classLoader) throws PluginException { + this.pluginName = pluginName; try { interceptor = InterceptorInstanceLoader.load(constructorInterceptorClassName, classLoader); } catch (Throwable t) { @@ -59,13 +64,17 @@ public ConstructorInter(String constructorInterceptorClassName, ClassLoader clas */ @RuntimeType public void intercept(@This Object obj, @AllArguments Object[] allArguments) { + long interceptorTimeCost = 0L; + long startTime = System.nanoTime(); try { EnhancedInstance targetObject = (EnhancedInstance) obj; interceptor.onConstruct(targetObject, allArguments); } catch (Throwable t) { LOGGER.error("ConstructorInter failure.", t); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } - + interceptorTimeCost += System.nanoTime() - startTime; + AgentSo11y.durationOfInterceptor(interceptorTimeCost); } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/InstMethodsInter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/InstMethodsInter.java index 81ebfb1b78..581b854de3 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/InstMethodsInter.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/InstMethodsInter.java @@ -29,6 +29,7 @@ import org.apache.skywalking.apm.agent.core.plugin.PluginException; import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader; import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; /** * The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between @@ -37,6 +38,9 @@ public class InstMethodsInter { private static final ILog LOGGER = LogManager.getLogger(InstMethodsInter.class); + private static final String INTERCEPTOR_TYPE = "inst"; + + private String pluginName; /** * An {@link InstanceMethodsAroundInterceptor} This name should only stay in {@link String}, the real {@link Class} * type will trigger classloader failure. If you want to know more, please check on books about Classloader or @@ -47,7 +51,8 @@ public class InstMethodsInter { /** * @param instanceMethodsAroundInterceptorClassName class full name. */ - public InstMethodsInter(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) { + public InstMethodsInter(String pluginName, String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) { + this.pluginName = pluginName; try { interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader); } catch (Throwable t) { @@ -71,12 +76,16 @@ public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @ @Origin Method method) throws Throwable { EnhancedInstance targetObject = (EnhancedInstance) obj; + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInterceptResult result = new MethodInterceptResult(); try { interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), result); } catch (Throwable t) { LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -86,19 +95,27 @@ public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @ ret = zuper.call(); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t); } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret); } catch (Throwable t) { LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + AgentSo11y.durationOfInterceptor(interceptorTimeCost); + return ret; } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/InstMethodsInterWithOverrideArgs.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/InstMethodsInterWithOverrideArgs.java index 1bba49c177..fabe5094e3 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/InstMethodsInterWithOverrideArgs.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/InstMethodsInterWithOverrideArgs.java @@ -28,6 +28,7 @@ import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader; 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.agent.core.so11y.AgentSo11y; /** * The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between @@ -36,6 +37,9 @@ public class InstMethodsInterWithOverrideArgs { private static final ILog LOGGER = LogManager.getLogger(InstMethodsInterWithOverrideArgs.class); + private static final String INTERCEPTOR_TYPE = "inst"; + + private String pluginName; /** * An {@link InstanceMethodsAroundInterceptor} This name should only stay in {@link String}, the real {@link Class} * type will trigger classloader failure. If you want to know more, please check on books about Classloader or @@ -46,7 +50,8 @@ public class InstMethodsInterWithOverrideArgs { /** * @param instanceMethodsAroundInterceptorClassName class full name. */ - public InstMethodsInterWithOverrideArgs(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) { + public InstMethodsInterWithOverrideArgs(String pluginName, String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) { + this.pluginName = pluginName; try { interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader); } catch (Throwable t) { @@ -70,12 +75,16 @@ public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @ @Morph OverrideCallable zuper) throws Throwable { EnhancedInstance targetObject = (EnhancedInstance) obj; + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInterceptResult result = new MethodInterceptResult(); try { interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), result); } catch (Throwable t) { LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -85,19 +94,26 @@ public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @ ret = zuper.call(allArguments); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t); } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret); } catch (Throwable t) { LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + AgentSo11y.durationOfInterceptor(interceptorTimeCost); return ret; } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/StaticMethodsInter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/StaticMethodsInter.java index 6507118aaf..c1f3564dfe 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/StaticMethodsInter.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/StaticMethodsInter.java @@ -27,6 +27,7 @@ import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader; 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.agent.core.so11y.AgentSo11y; /** * The actual byte-buddy's interceptor to intercept class static methods. In this class, it provides a bridge between @@ -35,6 +36,9 @@ public class StaticMethodsInter { private static final ILog LOGGER = LogManager.getLogger(StaticMethodsInter.class); + private static final String INTERCEPTOR_TYPE = "static"; + + private String pluginName; /** * A class full name, and instanceof {@link StaticMethodsAroundInterceptor} This name should only stay in {@link * String}, the real {@link Class} type will trigger classloader failure. If you want to know more, please check on @@ -47,7 +51,8 @@ public class StaticMethodsInter { * * @param staticMethodsAroundInterceptorClassName class full name. */ - public StaticMethodsInter(String staticMethodsAroundInterceptorClassName) { + public StaticMethodsInter(String pluginName, String staticMethodsAroundInterceptorClassName) { + this.pluginName = pluginName; this.staticMethodsAroundInterceptorClassName = staticMethodsAroundInterceptorClassName; } @@ -68,12 +73,16 @@ public Object intercept(@Origin Class clazz, @AllArguments Object[] allArgume StaticMethodsAroundInterceptor interceptor = InterceptorInstanceLoader.load(staticMethodsAroundInterceptorClassName, clazz .getClassLoader()); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInterceptResult result = new MethodInterceptResult(); try { interceptor.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), result); } catch (Throwable t) { LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -83,19 +92,27 @@ public Object intercept(@Origin Class clazz, @AllArguments Object[] allArgume ret = zuper.call(); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { interceptor.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t); } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { ret = interceptor.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret); } catch (Throwable t) { LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + AgentSo11y.durationOfInterceptor(interceptorTimeCost); + return ret; } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/StaticMethodsInterWithOverrideArgs.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/StaticMethodsInterWithOverrideArgs.java index 83e66e4bcd..23b136fdcf 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/StaticMethodsInterWithOverrideArgs.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/StaticMethodsInterWithOverrideArgs.java @@ -26,6 +26,7 @@ import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader; 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.agent.core.so11y.AgentSo11y; /** * The actual byte-buddy's interceptor to intercept class static methods. In this class, it provides a bridge between @@ -34,6 +35,9 @@ public class StaticMethodsInterWithOverrideArgs { private static final ILog LOGGER = LogManager.getLogger(StaticMethodsInterWithOverrideArgs.class); + private static final String INTERCEPTOR_TYPE = "static"; + + private String pluginName; /** * A class full name, and instanceof {@link StaticMethodsAroundInterceptor} This name should only stay in {@link * String}, the real {@link Class} type will trigger classloader failure. If you want to know more, please check on @@ -44,9 +48,11 @@ public class StaticMethodsInterWithOverrideArgs { /** * Set the name of {@link StaticMethodsInterWithOverrideArgs#staticMethodsAroundInterceptorClassName} * + * @param pluginName name of interceptor plugin * @param staticMethodsAroundInterceptorClassName class full name. */ - public StaticMethodsInterWithOverrideArgs(String staticMethodsAroundInterceptorClassName) { + public StaticMethodsInterWithOverrideArgs(String pluginName, String staticMethodsAroundInterceptorClassName) { + this.pluginName = pluginName; this.staticMethodsAroundInterceptorClassName = staticMethodsAroundInterceptorClassName; } @@ -67,12 +73,16 @@ public Object intercept(@Origin Class clazz, @AllArguments Object[] allArgume StaticMethodsAroundInterceptor interceptor = InterceptorInstanceLoader.load(staticMethodsAroundInterceptorClassName, clazz .getClassLoader()); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInterceptResult result = new MethodInterceptResult(); try { interceptor.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), result); } catch (Throwable t) { LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -82,19 +92,27 @@ public Object intercept(@Origin Class clazz, @AllArguments Object[] allArgume ret = zuper.call(allArguments); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { interceptor.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t); } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { ret = interceptor.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret); } catch (Throwable t) { LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + AgentSo11y.durationOfInterceptor(interceptorTimeCost); + return ret; } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/ClassEnhancePluginDefineV2.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/ClassEnhancePluginDefineV2.java index 2436c2994b..8ea6cdfb99 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/ClassEnhancePluginDefineV2.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/ClassEnhancePluginDefineV2.java @@ -87,7 +87,7 @@ protected DynamicType.Builder enhanceClass(TypeDescription typeDescription, isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher())) .intercept(MethodDelegation.withDefaultConfiguration() .withBinders(Morph.Binder.install(OverrideCallable.class)) - .to(new StaticMethodsInterV2WithOverrideArgs(interceptor), delegateNamingResolver.resolve(staticMethodsInterceptV2Point))); + .to(new StaticMethodsInterV2WithOverrideArgs(getPluginName(), interceptor), delegateNamingResolver.resolve(staticMethodsInterceptV2Point))); } } else { if (isBootstrapInstrumentation()) { @@ -99,7 +99,7 @@ protected DynamicType.Builder enhanceClass(TypeDescription typeDescription, newClassBuilder = newClassBuilder.method( isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher())) .intercept(MethodDelegation.withDefaultConfiguration() - .to(new StaticMethodsInterV2(interceptor), delegateNamingResolver.resolve(staticMethodsInterceptV2Point))); + .to(new StaticMethodsInterV2(getPluginName(), interceptor), delegateNamingResolver.resolve(staticMethodsInterceptV2Point))); } } @@ -151,7 +151,7 @@ protected DynamicType.Builder enhanceInstance(TypeDescription typeDescription } else { newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()) .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration() - .to(new ConstructorInter(constructorInterceptPoint + .to(new ConstructorInter(getPluginName(), constructorInterceptPoint .getConstructorInterceptor(), classLoader), fieldNamingResolver.resolve(constructorInterceptPoint)))); } } @@ -179,7 +179,7 @@ protected DynamicType.Builder enhanceInstance(TypeDescription typeDescription newClassBuilder = newClassBuilder.method(junction) .intercept(MethodDelegation.withDefaultConfiguration() .withBinders(Morph.Binder.install(OverrideCallable.class)) - .to(new InstMethodsInterV2WithOverrideArgs(interceptor, classLoader), fieldNamingResolver.resolve(instanceMethodsInterceptV2Point))); + .to(new InstMethodsInterV2WithOverrideArgs(getPluginName(), interceptor, classLoader), fieldNamingResolver.resolve(instanceMethodsInterceptV2Point))); } } else { if (isBootstrapInstrumentation()) { @@ -189,7 +189,7 @@ protected DynamicType.Builder enhanceInstance(TypeDescription typeDescription } else { newClassBuilder = newClassBuilder.method(junction) .intercept(MethodDelegation.withDefaultConfiguration() - .to(new InstMethodsInterV2(interceptor, classLoader), fieldNamingResolver.resolve(instanceMethodsInterceptV2Point))); + .to(new InstMethodsInterV2(getPluginName(), interceptor, classLoader), fieldNamingResolver.resolve(instanceMethodsInterceptV2Point))); } } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/InstMethodsInterV2.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/InstMethodsInterV2.java index 8638980931..a46092ad92 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/InstMethodsInterV2.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/InstMethodsInterV2.java @@ -29,6 +29,7 @@ import org.apache.skywalking.apm.agent.core.plugin.PluginException; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; /** * The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between @@ -37,9 +38,13 @@ public class InstMethodsInterV2 { private static final ILog LOGGER = LogManager.getLogger(InstMethodsInterV2.class); + private static final String INTERCEPTOR_TYPE = "inst"; + + private String pluginName; private InstanceMethodsAroundInterceptorV2 interceptor; - public InstMethodsInterV2(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) { + public InstMethodsInterV2(String pluginName, String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) { + this.pluginName = pluginName; try { interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader); } catch (Throwable t) { @@ -52,12 +57,16 @@ public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @ @Origin Method method) throws Throwable { EnhancedInstance targetObject = (EnhancedInstance) obj; + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInvocationContext context = new MethodInvocationContext(); try { interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context); } catch (Throwable t) { LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -67,19 +76,27 @@ public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @ ret = zuper.call(); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context); } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context); } catch (Throwable t) { LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + AgentSo11y.durationOfInterceptor(interceptorTimeCost); + return ret; } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/InstMethodsInterV2WithOverrideArgs.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/InstMethodsInterV2WithOverrideArgs.java index 5779a386f1..2a937c961a 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/InstMethodsInterV2WithOverrideArgs.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/InstMethodsInterV2WithOverrideArgs.java @@ -30,6 +30,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable; import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; /** * The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between @@ -38,6 +39,9 @@ public class InstMethodsInterV2WithOverrideArgs { private static final ILog LOGGER = LogManager.getLogger(InstMethodsInterV2WithOverrideArgs.class); + private static final String INTERCEPTOR_TYPE = "inst"; + + private String pluginName; /** * An {@link InstanceMethodsAroundInterceptorV2} This name should only stay in {@link String}, the real {@link Class} * type will trigger classloader failure. If you want to know more, please check on books about Classloader or @@ -48,7 +52,8 @@ public class InstMethodsInterV2WithOverrideArgs { /** * @param instanceMethodsAroundInterceptorClassName class full name. */ - public InstMethodsInterV2WithOverrideArgs(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) { + public InstMethodsInterV2WithOverrideArgs(String pluginName, String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) { + this.pluginName = pluginName; try { interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader); } catch (Throwable t) { @@ -72,12 +77,16 @@ public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @ @Morph OverrideCallable zuper) throws Throwable { EnhancedInstance targetObject = (EnhancedInstance) obj; + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInvocationContext context = new MethodInvocationContext(); try { interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context); } catch (Throwable t) { LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -87,19 +96,27 @@ public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @ ret = zuper.call(allArguments); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context); } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context); } catch (Throwable t) { LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + AgentSo11y.durationOfInterceptor(interceptorTimeCost); + return ret; } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/StaticMethodsInterV2.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/StaticMethodsInterV2.java index 677ffa3697..add92b4fe1 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/StaticMethodsInterV2.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/StaticMethodsInterV2.java @@ -27,6 +27,7 @@ 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.agent.core.plugin.loader.InterceptorInstanceLoader; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; /** * The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between @@ -35,6 +36,9 @@ public class StaticMethodsInterV2 { private static final ILog LOGGER = LogManager.getLogger(StaticMethodsInterV2.class); + private static final String INTERCEPTOR_TYPE = "static"; + + private String pluginName; /** * A class full name, and instanceof {@link StaticMethodsAroundInterceptorV2} This name should only stay in {@link * String}, the real {@link Class} type will trigger classloader failure. If you want to know more, please check on @@ -47,7 +51,8 @@ public class StaticMethodsInterV2 { * * @param staticMethodsAroundInterceptorClassName class full name. */ - public StaticMethodsInterV2(String staticMethodsAroundInterceptorClassName) { + public StaticMethodsInterV2(String pluginName, String staticMethodsAroundInterceptorClassName) { + this.pluginName = pluginName; this.staticMethodsAroundInterceptorClassName = staticMethodsAroundInterceptorClassName; } @@ -68,12 +73,16 @@ public Object intercept(@Origin Class clazz, @AllArguments Object[] allArgume StaticMethodsAroundInterceptorV2 interceptor = InterceptorInstanceLoader.load(staticMethodsAroundInterceptorClassName, clazz.getClassLoader()); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInvocationContext context = new MethodInvocationContext(); try { interceptor.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), context); } catch (Throwable t) { LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -83,19 +92,27 @@ public Object intercept(@Origin Class clazz, @AllArguments Object[] allArgume ret = zuper.call(); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { interceptor.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context); } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { ret = interceptor.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context); } catch (Throwable t) { LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + AgentSo11y.durationOfInterceptor(interceptorTimeCost); + return ret; } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/StaticMethodsInterV2WithOverrideArgs.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/StaticMethodsInterV2WithOverrideArgs.java index e7d326b43a..0341e67d0d 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/StaticMethodsInterV2WithOverrideArgs.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/StaticMethodsInterV2WithOverrideArgs.java @@ -27,6 +27,7 @@ import org.apache.skywalking.apm.agent.core.logging.api.LogManager; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable; import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; /** * The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provides a bridge between @@ -35,6 +36,9 @@ public class StaticMethodsInterV2WithOverrideArgs { private static final ILog LOGGER = LogManager.getLogger(StaticMethodsInterV2WithOverrideArgs.class); + private static final String INTERCEPTOR_TYPE = "static"; + + private String pluginName; /** * A class full name, and instanceof {@link StaticMethodsAroundInterceptorV2} This name should only stay in {@link * String}, the real {@link Class} type will trigger classloader failure. If you want to know more, please check on @@ -47,7 +51,8 @@ public class StaticMethodsInterV2WithOverrideArgs { * * @param staticMethodsAroundInterceptorClassName class full name. */ - public StaticMethodsInterV2WithOverrideArgs(String staticMethodsAroundInterceptorClassName) { + public StaticMethodsInterV2WithOverrideArgs(String pluginName, String staticMethodsAroundInterceptorClassName) { + this.pluginName = pluginName; this.staticMethodsAroundInterceptorClassName = staticMethodsAroundInterceptorClassName; } @@ -68,12 +73,16 @@ public Object intercept(@Origin Class clazz, @AllArguments Object[] allArgume StaticMethodsAroundInterceptorV2 interceptor = InterceptorInstanceLoader.load(staticMethodsAroundInterceptorClassName, clazz.getClassLoader()); + long interceptorTimeCost = 0L; + long startTimeOfMethodBeforeInter = System.nanoTime(); MethodInvocationContext context = new MethodInvocationContext(); try { interceptor.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), context); } catch (Throwable t) { LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodBeforeInter; Object ret = null; try { @@ -83,19 +92,27 @@ public Object intercept(@Origin Class clazz, @AllArguments Object[] allArgume ret = zuper.call(allArguments); } } catch (Throwable t) { + long startTimeOfMethodHandleExceptionInter = System.nanoTime(); try { interceptor.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context); } catch (Throwable t2) { LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodHandleExceptionInter; throw t; } finally { + long startTimeOfMethodAfterInter = System.nanoTime(); try { ret = interceptor.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context); } catch (Throwable t) { LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage()); + AgentSo11y.errorOfPlugin(pluginName, INTERCEPTOR_TYPE); } + interceptorTimeCost += System.nanoTime() - startTimeOfMethodAfterInter; } + AgentSo11y.durationOfInterceptor(interceptorTimeCost); + return ret; } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java new file mode 100644 index 0000000000..b1468f293a --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java @@ -0,0 +1,153 @@ +/* + * 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.agent.core.so11y; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.apache.skywalking.apm.agent.core.meter.Counter; +import org.apache.skywalking.apm.agent.core.meter.Histogram; +import org.apache.skywalking.apm.agent.core.meter.MeterFactory; + +/** + * Agent self-observability meters collect through skywalking native protocols + */ +public class AgentSo11y { + + // A map to cache meter obj(s) for plugins. The key is the plugin name. + private static final Map ERROR_COUNTER_CACHE = new ConcurrentHashMap<>(); + + // Steps of interceptor time cost histogram + private static final List TIME_COST_HISTOGRAM_STEPS = Arrays.asList( + 1000d, 10000d, 50000d, 100000d, 300000d, 500000d, + 1000000d, 5000000d, 10000000d, 20000000d, 50000000d, 100000000d + ); + + // context counter + private static Counter PROPAGATED_CONTEXT_COUNTER; + private static Counter SAMPLER_CONTEXT_COUNTER; + private static Counter FINISH_CONTEXT_COUNTER; + + // ignore context counter + private static Counter PROPAGATED_IGNORE_CONTEXT_COUNTER; + private static Counter SAMPLER_IGNORE_CONTEXT_COUNTER; + private static Counter FINISH_IGNORE_CONTEXT_COUNTER; + + // leaked context counter + private static Counter LEAKED_CONTEXT_COUNTER; + private static Counter LEAKED_IGNORE_CONTEXT_COUNTER; + + // context perf histogram + private static Histogram INTERCEPTOR_TIME_COST; + + public static void measureTracingContextCreation(boolean forceSampling, boolean ignoredTracingContext) { + if (forceSampling) { + if (ignoredTracingContext) { + if (PROPAGATED_IGNORE_CONTEXT_COUNTER == null) { + PROPAGATED_IGNORE_CONTEXT_COUNTER = MeterFactory + .counter("created_ignored_context_counter") + .tag("created_by", "propagated") + .build(); + } + PROPAGATED_IGNORE_CONTEXT_COUNTER.increment(1); + } else { + if (PROPAGATED_CONTEXT_COUNTER == null) { + PROPAGATED_CONTEXT_COUNTER = MeterFactory + .counter("created_tracing_context_counter") + .tag("created_by", "propagated") + .build(); + } + PROPAGATED_CONTEXT_COUNTER.increment(1); + } + } else { + if (ignoredTracingContext) { + if (SAMPLER_IGNORE_CONTEXT_COUNTER == null) { + SAMPLER_IGNORE_CONTEXT_COUNTER = MeterFactory + .counter("created_ignored_context_counter") + .tag("created_by", "sampler") + .build(); + } + SAMPLER_IGNORE_CONTEXT_COUNTER.increment(1); + } else { + if (SAMPLER_CONTEXT_COUNTER == null) { + SAMPLER_CONTEXT_COUNTER = MeterFactory + .counter("created_tracing_context_counter") + .tag("created_by", "sampler") + .build(); + } + SAMPLER_CONTEXT_COUNTER.increment(1); + } + } + } + + public static void measureTracingContextCompletion(boolean ignoredTracingContext) { + if (ignoredTracingContext) { + if (FINISH_IGNORE_CONTEXT_COUNTER == null) { + FINISH_IGNORE_CONTEXT_COUNTER = MeterFactory.counter("finished_ignored_context_counter").build(); + } + FINISH_IGNORE_CONTEXT_COUNTER.increment(1); + } else { + if (FINISH_CONTEXT_COUNTER == null) { + FINISH_CONTEXT_COUNTER = MeterFactory.counter("finished_tracing_context_counter").build(); + } + FINISH_CONTEXT_COUNTER.increment(1); + } + } + + public static void measureLeakedTracingContext(boolean ignoredTracingContext) { + if (ignoredTracingContext) { + if (LEAKED_IGNORE_CONTEXT_COUNTER == null) { + LEAKED_IGNORE_CONTEXT_COUNTER = MeterFactory + .counter("possible_leaked_context_counter") + .tag("source", "ignore") + .build(); + } + LEAKED_IGNORE_CONTEXT_COUNTER.increment(1); + } else { + if (LEAKED_CONTEXT_COUNTER == null) { + LEAKED_CONTEXT_COUNTER = MeterFactory + .counter("possible_leaked_context_counter") + .tag("source", "tracing") + .build(); + } + LEAKED_CONTEXT_COUNTER.increment(1); + } + } + + public static void durationOfInterceptor(double timeCostInNanos) { + if (INTERCEPTOR_TIME_COST == null) { + INTERCEPTOR_TIME_COST = MeterFactory + .histogram("tracing_context_performance") + .steps(TIME_COST_HISTOGRAM_STEPS) + .build(); + } + INTERCEPTOR_TIME_COST.addValue(timeCostInNanos); + } + + public static void errorOfPlugin(String pluginName, String interType) { + Counter counter = ERROR_COUNTER_CACHE.computeIfAbsent(pluginName + interType, key -> MeterFactory + .counter("interceptor_error_counter") + .tag("plugin_name", pluginName) + .tag("inter_type", interType) + .build() + ); + counter.increment(1); + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/bootstrap/BootstrapPluginSo11y.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/bootstrap/BootstrapPluginSo11y.java new file mode 100644 index 0000000000..e0032ac7d3 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/bootstrap/BootstrapPluginSo11y.java @@ -0,0 +1,25 @@ +/* + * 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.agent.core.so11y.bootstrap; + +public interface BootstrapPluginSo11y { + void duration(double timeCostInNanos); + + void error(String pluginName, String interType); +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/bootstrap/BootstrapPluginSo11yBridge.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/bootstrap/BootstrapPluginSo11yBridge.java new file mode 100644 index 0000000000..2c9ac37600 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/bootstrap/BootstrapPluginSo11yBridge.java @@ -0,0 +1,46 @@ +/* + * 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.agent.core.so11y.bootstrap; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist; +import org.apache.skywalking.apm.agent.core.so11y.AgentSo11y; + +/** + * used by {@link BootstrapInterRuntimeAssist} + */ +@SuppressWarnings("unused") +public class BootstrapPluginSo11yBridge implements BootstrapPluginSo11y { + + public static BootstrapPluginSo11y getSo11y() { + return new BootstrapPluginSo11yBridge(); + } + + private BootstrapPluginSo11yBridge() { + } + + @Override + public void duration(final double timeCostInNanos) { + AgentSo11y.durationOfInterceptor(timeCostInNanos); + } + + @Override + public void error(final String pluginName, final String interType) { + AgentSo11y.errorOfPlugin(pluginName, interType); + } +} diff --git a/docs/en/setup/service-agent/java-agent/Agent-self-observability.md b/docs/en/setup/service-agent/java-agent/Agent-self-observability.md new file mode 100644 index 0000000000..7efa7ee1b4 --- /dev/null +++ b/docs/en/setup/service-agent/java-agent/Agent-self-observability.md @@ -0,0 +1,16 @@ +# Agent Self Observability +The Java Agent self-observability feature is built-in and used to measure the tracing performance and error statistics of plugins. + +It reports meters to SkyWalking oap through native meter protocol, OAP receives and analyzes meters, +which are ultimately presented on the [Java Agent self-observability dashboard](https://skywalking.apache.org/docs/main/next/en/setup/backend/dashboards-so11y-java-agent/). + +***Note: Java Agent self-observability dashboard is available since OAP 10.1.0*** + +# Details of agent so11y meters +- `created_tracing_context_counter` - Counter. The number of created tracing contexts. This includes a label=created_by(value=sampler,propagated). `created_by=propagated` means the agent created the context due to downstream service added sw8 header to trigger force sampling. `created_by=sampler` means the agent created this context by local sampler no matter which policy it uses. +- `finished_tracing_context_counter` - Counter. The number of finished contexts. The gap between `finished_tracing_context_counter` and `created_tracing_context_counter` should be relatively stable, otherwise, the memory cost would be increased. +- `created_ignored_context_counter` and `finished_ignored_context_counter`. Same concepts like `*_tracing_context_counter`. +- `interceptor_error_counter` - Counter. The number of errors happened in the interceptor logic, with `label=plugin_name, inter_type(constructor, inst, static)`. We don't add interceptor names into labels in case of OOM. The number of plugins is only dozens, it is predictable, but the number of interceptors will be hundreds. +- `possible_leaked_context_counter` - Counter. The number of detected leaked contexts. It should include the `label=source(value=tracing, ignore)`. When `source=tracing`, it is today's shadow tracing context. But now, it is measured. +- `tracing_context_performance` - Histogram. For successfully finished tracing context, it measures every interceptor's time cost(by using nanoseconds), the buckets of the histogram are {1000, 10000, 50000, 100000, 300000, 500000, + 1000000, 5000000, 10000000, 20000000, 50000000, 100000000}ns. This provides the performance behavior for the tracing operations. \ No newline at end of file diff --git a/docs/en/setup/service-agent/java-agent/Plugin-test.md b/docs/en/setup/service-agent/java-agent/Plugin-test.md index e67c365672..c91402e6c5 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-test.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-test.md @@ -107,7 +107,7 @@ File Name | Descriptions | startScript | Path of the start up script. Required in `type: jvm` only. | runningMode | Running mode with the optional plugin, options, `default`(default), `with_optional`, or `with_bootstrap`. | withPlugins | Plugin selector rule, e.g.:`apm-spring-annotation-plugin-*.jar`. Required for `runningMode=with_optional` or `runningMode=with_bootstrap`. -| environment | Same as `docker-compose#environment`. +| environment | Same as `docker-compose#environment` and also used as `docker run` environment variables. | depends_on | Same as `docker-compose#depends_on`. | dependencies | Same as `docker-compose#services`, `image`, `links`, `hostname`, `command`, `environment` and `depends_on` are supported. diff --git a/docs/menu.yml b/docs/menu.yml index 3964b059be..7bfc420672 100644 --- a/docs/menu.yml +++ b/docs/menu.yml @@ -88,7 +88,11 @@ catalog: path: "/en/setup/service-agent/java-agent/configuration-discovery" - name: "Advanced reporters" path: "/en/setup/service-agent/java-agent/advanced-reporters" - - name: "Plugin development guide" + - name: "Agent Self Observability" + path: "/en/setup/service-agent/java-agent/Agent-self-observability" + - name: "Plugin Test Guide" + path: "/en/setup/service-agent/java-agent/Plugin-test/" + - name: "Plugin Development Guide" path: "/en/setup/service-agent/java-agent/java-plugin-development-guide/" - name: "Java Agent Performance Test" path: "https://skyapmtest.github.io/Agent-Benchmarks/" diff --git a/test/plugin/runner-helper/src/main/resources/compose-start-script.template b/test/plugin/runner-helper/src/main/resources/compose-start-script.template index 6ee08de4b5..3ef6a15466 100644 --- a/test/plugin/runner-helper/src/main/resources/compose-start-script.template +++ b/test/plugin/runner-helper/src/main/resources/compose-start-script.template @@ -26,7 +26,7 @@ docker_container_name="${docker_container_name}_1" <#noparse> container_name="${project_name}_${docker_container_name}" -docker-compose -p ${project_name} -f ${compose_file} up -d +docker compose -p ${project_name} -f ${compose_file} up -d container_id=`docker ps -qf "name=${container_name}"` if [[ -z "${container_id}" ]]; then @@ -38,8 +38,8 @@ else [[ $status -ne 0 ]] && docker logs ${container_id} >&2 docker logs ${container_id} >${SCENARIO_HOME}/logs/container.log - docker-compose -p ${project_name} -f ${compose_file} kill - docker-compose -p ${project_name} -f ${compose_file} rm -f + docker compose -p ${project_name} -f ${compose_file} kill + docker compose -p ${project_name} -f ${compose_file} rm -f fi diff --git a/test/plugin/runner-helper/src/main/resources/container-start-script.template b/test/plugin/runner-helper/src/main/resources/container-start-script.template index 108fb0bf20..0f072afdf1 100644 --- a/test/plugin/runner-helper/src/main/resources/container-start-script.template +++ b/test/plugin/runner-helper/src/main/resources/container-start-script.template @@ -33,6 +33,11 @@ docker run -d \ <#if debug_mode??> --env DEBUG_MODE=${debug_mode} \ + <#if environments??> + <#list environments as env> + --env ${env} \ + + -v ${agent_home}:/usr/local/skywalking/scenario/agent \ -v ${scenario_home}:/usr/local/skywalking/scenario \ -v ${jacoco_home}:/jacoco \ diff --git a/test/plugin/scenarios/agent-so11y-scenario/bin/startup.sh b/test/plugin/scenarios/agent-so11y-scenario/bin/startup.sh new file mode 100644 index 0000000000..e4140338be --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-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/agent-so11y-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/agent-so11y-scenario/config/expectedData.yaml b/test/plugin/scenarios/agent-so11y-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..8e044e041f --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-scenario/config/expectedData.yaml @@ -0,0 +1,177 @@ +# 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: agent-so11y-scenario + segmentSize: gt 1 + segments: + - segmentId: not null + spans: + - operationName: H2/JDBC/PreparedStatement/execute + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 32 + isError: false + spanType: Exit + peer: localhost:-1 + tags: + - {key: db.type, value: H2} + - {key: db.instance, value: test} + - key: db.statement + value: "CREATE TABLE test_007(\nid VARCHAR(1) PRIMARY KEY, \nvalue VARCHAR(1)\ + \ NOT NULL)" + skipAnalysis: 'false' + - operationName: H2/JDBC/CallableStatement/execute + parentSpanId: 0 + spanId: 2 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 32 + isError: false + spanType: Exit + peer: localhost:-1 + tags: + - {key: db.type, value: H2} + - {key: db.instance, value: test} + - {key: db.statement, value: 'INSERT INTO test_007(id, value) VALUES(?,?)'} + skipAnalysis: 'false' + - operationName: H2/JDBC/Statement/execute + parentSpanId: 0 + spanId: 3 + spanLayer: Database + startTime: gt 0 + endTime: gt 0 + componentId: 32 + isError: false + spanType: Exit + peer: localhost:-1 + tags: + - {key: db.type, value: H2} + - {key: db.instance, value: test} + - {key: db.statement, value: DROP table test_007} + skipAnalysis: 'false' + - operationName: /agent-so11y-scenario/case/ignore.html + parentSpanId: 0 + spanId: 4 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 66 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/agent-so11y-scenario/case/ignore.html'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /agent-so11y-scenario/case/propagated + parentSpanId: 0 + spanId: 5 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 66 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/agent-so11y-scenario/case/propagated'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: GET:/agent-so11y-scenario/case/agent-so11y-scenario + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/agent-so11y-scenario/case/agent-so11y-scenario'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GET:/agent-so11y-scenario/case/propagated + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/agent-so11y-scenario/case/propagated'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + refs: + - {parentEndpoint: 'GET:/agent-so11y-scenario/case/agent-so11y-scenario', networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 5, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: agent-so11y-scenario, + traceId: not null} + +meterItems: +- serviceName: agent-so11y-scenario + meterSize: ge 9 + meters: + - meterId: + name: created_tracing_context_counter + tags: + - {name: created_by, value: propagated} + singleValue: 1.0 + - meterId: + name: created_tracing_context_counter + tags: + - {name: created_by, value: sampler} + singleValue: 1.0 + - meterId: + name: finished_tracing_context_counter + tags: [] + singleValue: 2.0 + - meterId: + name: created_ignored_context_counter + tags: + - {name: created_by, value: propagated} + singleValue: 1.0 + - meterId: + name: created_ignored_context_counter + tags: + - {name: created_by, value: sampler} + singleValue: 1.0 + - meterId: + name: finished_ignored_context_counter + tags: [] + singleValue: 2.0 + - meterId: + name: tracing_context_performance + tags: [] + histogramBuckets: [0.0, 1000.0, 10000.0, 50000.0, 100000.0, 300000.0, 500000.0, 1000000.0, 5000000.0, 1.0E7, 2.0E7, 5.0E7, 1.0E8] + - meterId: + name: possible_leaked_context_counter + tags: + - {name: source, value: tracing} + singleValue: 1.0 diff --git a/test/plugin/scenarios/agent-so11y-scenario/configuration.yml b/test/plugin/scenarios/agent-so11y-scenario/configuration.yml new file mode 100644 index 0000000000..7d9a31395c --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-scenario/configuration.yml @@ -0,0 +1,25 @@ +# 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/agent-so11y-scenario/case/agent-so11y-scenario +healthCheck: http://localhost:8080/agent-so11y-scenario/case/healthCheck.html +runningMode: with_bootstrap +withPlugins: apm-jdk-http-plugin-*.jar +startScript: ./bin/startup.sh +environment: + - SW_AGENT_SPAN_LIMIT=6 + - SW_METER_REPORT_INTERVAL=1 diff --git a/test/plugin/scenarios/agent-so11y-scenario/pom.xml b/test/plugin/scenarios/agent-so11y-scenario/pom.xml new file mode 100644 index 0000000000..39095c57ad --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-scenario/pom.xml @@ -0,0 +1,128 @@ + + + + + org.apache.skywalking.apm.testcase + agent-so11y-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + 1.0.0 + 1.4.177 + 2.5.6 + 1.18.20 + + + skywalking-agent-so11y-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + com.h2database + h2 + ${h2.version} + + + + + agent-so11y-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + diff --git a/test/plugin/scenarios/agent-so11y-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/agent-so11y-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..abd3f9e799 --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/agent-so11y-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/Application.java b/test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/Application.java new file mode 100644 index 0000000000..e063f8d641 --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/Application.java @@ -0,0 +1,30 @@ +/* + * 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.testcase.h2; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/controller/CaseController.java b/test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/controller/CaseController.java new file mode 100644 index 0000000000..ee8760cb50 --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/controller/CaseController.java @@ -0,0 +1,76 @@ +/* + * 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.testcase.h2.controller; + +import java.net.URL; +import lombok.extern.log4j.Log4j2; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +@Log4j2 +public class CaseController { + + private static final String SUCCESS = "Success"; + + private static final String CREATE_TABLE_SQL = "CREATE TABLE test_007(\n" + + "id VARCHAR(1) PRIMARY KEY, \n" + + "value VARCHAR(1) NOT NULL)"; + private static final String INSERT_DATA_SQL = "INSERT INTO test_007(id, value) VALUES(?,?)"; + private static final String DROP_TABLE_SQL = "DROP table test_007"; + + @RequestMapping("/healthCheck.html") + @ResponseBody + public String healthCheck() { + // your codes + return SUCCESS; + } + + @RequestMapping("/agent-so11y-scenario") + @ResponseBody + public String testcase() throws Exception { + try (SQLExecutor sqlExecute = new SQLExecutor()) { + sqlExecute.createTable(CREATE_TABLE_SQL); + sqlExecute.insertData(INSERT_DATA_SQL, "1", "1"); + sqlExecute.dropTable(DROP_TABLE_SQL); + + // test bootstrap plugin & ignore context counter + new URL("http://localhost:8080/agent-so11y-scenario/case/ignore.html").getContent(); + new URL("http://localhost:8080/agent-so11y-scenario/case/propagated").getContent(); + } catch (Exception e) { + log.error("Failed to execute sql.", e); + throw e; + } + return SUCCESS; + } + + @RequestMapping("/ignore.html") + @ResponseBody + public String ignorePath() { + return SUCCESS; + } + + @RequestMapping("/propagated") + @ResponseBody + public String propagated() { + return SUCCESS; + } +} diff --git a/test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/controller/SQLExecutor.java b/test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/controller/SQLExecutor.java new file mode 100644 index 0000000000..1f6e3b3463 --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-scenario/src/main/java/org/apache/skywalking/apm/testcase/h2/controller/SQLExecutor.java @@ -0,0 +1,75 @@ +/* + * 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.testcase.h2.controller; + +import java.sql.CallableStatement; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +public class SQLExecutor implements AutoCloseable { + + private static final String URL = "jdbc:h2:mem:test"; + private static final String USERNAME = "root"; + private static final String PASSWORD = "root"; + + private Connection connection; + + public SQLExecutor() throws SQLException { + try { + Class.forName("org.h2.Driver"); + } catch (ClassNotFoundException e) { + // + } + connection = DriverManager.getConnection(URL, USERNAME, PASSWORD); + } + + public void createTable(String sql) throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement(sql); + preparedStatement.execute(); + preparedStatement.close(); + } + + public void insertData(String sql, String id, String value) throws SQLException { + CallableStatement preparedStatement = connection.prepareCall(sql); + preparedStatement.setString(1, id); + preparedStatement.setString(2, value); + preparedStatement.execute(); + preparedStatement.close(); + } + + public void dropTable(String sql) throws SQLException { + Statement preparedStatement = connection.createStatement(); + preparedStatement.execute(sql); + preparedStatement.close(); + } + + public void closeConnection() throws SQLException { + if (this.connection != null) { + this.connection.close(); + } + } + + @Override + public void close() throws Exception { + closeConnection(); + } +} diff --git a/test/plugin/scenarios/agent-so11y-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/agent-so11y-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..8e987fed1a --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-scenario/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +# +# 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 + servlet: + context-path: /agent-so11y-scenario +logging: + config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/agent-so11y-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/agent-so11y-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/agent-so11y-scenario/support-version.list b/test/plugin/scenarios/agent-so11y-scenario/support-version.list new file mode 100644 index 0000000000..293331ad63 --- /dev/null +++ b/test/plugin/scenarios/agent-so11y-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. + +1.0.0 diff --git a/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml b/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml index ab105a82ab..8c6b47877a 100644 --- a/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml @@ -492,7 +492,7 @@ segmentItems: skipAnalysis: 'true' meterItems: - serviceName: apm-toolkit-trace-scenario - meterSize: 8 + meterSize: ge 8 meters: - meterId: name: test_counter diff --git a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/config/expectedData.yaml index 545afa54ef..631a5bb4c3 100755 --- a/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/c3p0-0.9.0.x-0.9.1.x-scenario/config/expectedData.yaml @@ -212,7 +212,7 @@ segmentItems: - {key: http.status_code, value: '200'} meterItems: - serviceName: c3p0-0.9.0.x-0.9.1.x-scenario - meterSize: 12 + meterSize: ge 12 meters: - meterId: name: datasource diff --git a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/config/expectedData.yaml index 68f931fa29..35d6453291 100755 --- a/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/c3p0-0.9.2.x-0.10.x-scenario/config/expectedData.yaml @@ -212,7 +212,7 @@ segmentItems: - {key: http.status_code, value: '200'} meterItems: - serviceName: c3p0-0.9.2.x-0.10.x-scenario - meterSize: 12 + meterSize: ge 12 meters: - meterId: name: datasource diff --git a/test/plugin/scenarios/dbcp-2.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/dbcp-2.x-scenario/config/expectedData.yaml index 7e21e55dd6..4e3cb7c03a 100755 --- a/test/plugin/scenarios/dbcp-2.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/dbcp-2.x-scenario/config/expectedData.yaml @@ -224,7 +224,7 @@ segmentItems: - {key: http.status_code, value: '200'} meterItems: - serviceName: dbcp-2.x-scenario - meterSize: 12 + meterSize: ge 12 meters: - meterId: name: datasource diff --git a/test/plugin/scenarios/druid-1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/druid-1.x-scenario/config/expectedData.yaml index ca4a349b5b..fb32950056 100644 --- a/test/plugin/scenarios/druid-1.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/druid-1.x-scenario/config/expectedData.yaml @@ -206,7 +206,7 @@ segmentItems: - {key: http.status_code, value: '200'} meterItems: - serviceName: druid-1.x-scenario - meterSize: 13 + meterSize: ge 13 meters: - meterId: name: datasource diff --git a/test/plugin/scenarios/grizzly-2.3.x-4.x-workthreadpool-scenario/config/expectedData.yaml b/test/plugin/scenarios/grizzly-2.3.x-4.x-workthreadpool-scenario/config/expectedData.yaml index da0f47c6ab..a635342f8b 100644 --- a/test/plugin/scenarios/grizzly-2.3.x-4.x-workthreadpool-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/grizzly-2.3.x-4.x-workthreadpool-scenario/config/expectedData.yaml @@ -15,7 +15,7 @@ # limitations under the License. meterItems: - serviceName: grizzly-2.3.x-4.x-workthreadpool-scenario - meterSize: 4 + meterSize: ge 4 meters: - meterId: name: thread_pool diff --git a/test/plugin/scenarios/h2-scenario/config/expectedData.yaml b/test/plugin/scenarios/h2-scenario/config/expectedData.yaml index d06c487e8a..c1420faf08 100644 --- a/test/plugin/scenarios/h2-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/h2-scenario/config/expectedData.yaml @@ -98,7 +98,7 @@ segmentItems: skipAnalysis: 'false' meterItems: - serviceName: h2-scenario - meterSize: 5 + meterSize: ge 5 meters: - meterId: name: thread_pool diff --git a/test/plugin/scenarios/hikaricp-scenario/config/expectedData.yaml b/test/plugin/scenarios/hikaricp-scenario/config/expectedData.yaml index 75106a2a57..fbecf97a0a 100644 --- a/test/plugin/scenarios/hikaricp-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/hikaricp-scenario/config/expectedData.yaml @@ -206,7 +206,7 @@ segmentItems: - {key: http.status_code, value: '200'} meterItems: - serviceName: hikaricp-scenario - meterSize: 15 + meterSize: ge 15 meters: - meterId: name: datasource diff --git a/test/plugin/scenarios/jetty-11.x-thread-pool-scenario/config/expectedData.yaml b/test/plugin/scenarios/jetty-11.x-thread-pool-scenario/config/expectedData.yaml index d911caaa10..ff04156c69 100644 --- a/test/plugin/scenarios/jetty-11.x-thread-pool-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/jetty-11.x-thread-pool-scenario/config/expectedData.yaml @@ -15,7 +15,7 @@ # limitations under the License. meterItems: - serviceName: jetty-11.x-thread-pool-scenario - meterSize: 5 + meterSize: ge 5 meters: - meterId: name: thread_pool diff --git a/test/plugin/scenarios/jetty-thread-pool-scenario/config/expectedData.yaml b/test/plugin/scenarios/jetty-thread-pool-scenario/config/expectedData.yaml index 00b0074a84..276fa97406 100644 --- a/test/plugin/scenarios/jetty-thread-pool-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/jetty-thread-pool-scenario/config/expectedData.yaml @@ -15,7 +15,7 @@ # limitations under the License. meterItems: - serviceName: jetty-thread-pool-scenario - meterSize: 5 + meterSize: ge 5 meters: - meterId: name: thread_pool diff --git a/test/plugin/scenarios/tomcat-thread-pool-scenario/config/expectedData.yaml b/test/plugin/scenarios/tomcat-thread-pool-scenario/config/expectedData.yaml index 6a4cd68333..c4cc8f9ddd 100644 --- a/test/plugin/scenarios/tomcat-thread-pool-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/tomcat-thread-pool-scenario/config/expectedData.yaml @@ -15,7 +15,7 @@ # limitations under the License. meterItems: - serviceName: tomcat-thread-pool-scenario - meterSize: 5 + meterSize: ge 5 meters: - meterId: name: thread_pool diff --git a/test/plugin/scenarios/undertow-worker-thread-pool-scenario/config/expectedData.yaml b/test/plugin/scenarios/undertow-worker-thread-pool-scenario/config/expectedData.yaml index 32d7928752..424a39aee8 100644 --- a/test/plugin/scenarios/undertow-worker-thread-pool-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/undertow-worker-thread-pool-scenario/config/expectedData.yaml @@ -15,7 +15,7 @@ # limitations under the License. meterItems: - serviceName: undertow-worker-thread-pool-scenario - meterSize: 5 + meterSize: ge 5 meters: - meterId: name: thread_pool From 5c4970b51928c867bea2a3d71f78a371b80a4be3 Mon Sep 17 00:00:00 2001 From: yizhouw11 Date: Mon, 23 Sep 2024 15:32:23 +0800 Subject: [PATCH 030/114] Fix intermittent ClassCircularityError by preloading ThreadLocalRandom since ByteBuddy 1.12.11 (#718) --- CHANGES.md | 1 + .../apm/agent/core/plugin/PluginBootstrap.java | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index f2534d9be3..57fd985098 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ Release Notes. * Upgrade nats plugin to support 2.16.5 * Add agent self-observability. +* Fix intermittent ClassCircularityError by preloading ThreadLocalRandom since ByteBuddy 1.12.11 All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginBootstrap.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginBootstrap.java index 75c9edc6e0..bea0c3a7fa 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginBootstrap.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/PluginBootstrap.java @@ -33,6 +33,15 @@ public class PluginBootstrap { private static final ILog LOGGER = LogManager.getLogger(PluginBootstrap.class); + // Preload ThreadLocalRandom in case of intermittent ClassCircularityError since ByteBuddy 1.12.11 + static { + try { + Class.forName("java.util.concurrent.ThreadLocalRandom"); + } catch (Exception e) { + LOGGER.warn(e, "Preload ThreadLocalRandom failure."); + } + } + /** * load all plugins. * From 615a1b11bb49106ae9b8dc49da53caef2ec038ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Tue, 24 Sep 2024 09:45:16 +0800 Subject: [PATCH 031/114] Change so11y menu (#719) --- docs/menu.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/menu.yml b/docs/menu.yml index 7bfc420672..09729658a4 100644 --- a/docs/menu.yml +++ b/docs/menu.yml @@ -74,6 +74,8 @@ catalog: path: "/en/setup/service-agent/java-agent/application-toolkit-logback-1.x/" - name: "Logic Endpoint" path: "/en/setup/service-agent/java-agent/logic-endpoint" + - name: "Agent Self Observability" + path: "/en/setup/service-agent/java-agent/Agent-self-observability" - name: "Plugins" catalog: - name: "Supported middleware, framework and library" @@ -88,8 +90,6 @@ catalog: path: "/en/setup/service-agent/java-agent/configuration-discovery" - name: "Advanced reporters" path: "/en/setup/service-agent/java-agent/advanced-reporters" - - name: "Agent Self Observability" - path: "/en/setup/service-agent/java-agent/Agent-self-observability" - name: "Plugin Test Guide" path: "/en/setup/service-agent/java-agent/Plugin-test/" - name: "Plugin Development Guide" From 576550a8db6e1f98bfd3746aacafb0acbc3922b4 Mon Sep 17 00:00:00 2001 From: "Leibniz.Hu" Date: Mon, 28 Oct 2024 18:07:29 +0800 Subject: [PATCH 032/114] Add witness class/method for resteasy-server plugin (#722) --- CHANGES.md | 2 +- .../SynchronousDispatcherInstrumentation.java | 5 +++++ .../SynchronousDispatcherInstrumentation.java | 18 ++++++++++++++++++ .../SynchronousDispatcherInstrumentation.java | 18 ++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 57fd985098..270c4ab125 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,7 +8,7 @@ Release Notes. * Upgrade nats plugin to support 2.16.5 * Add agent self-observability. * Fix intermittent ClassCircularityError by preloading ThreadLocalRandom since ByteBuddy 1.12.11 - +* Add witness class/method for resteasy-server plugin(v3/v4/v6) All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v3/server/define/SynchronousDispatcherInstrumentation.java b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v3/server/define/SynchronousDispatcherInstrumentation.java index aaade19398..77093e85a8 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v3/server/define/SynchronousDispatcherInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v3/server/define/SynchronousDispatcherInstrumentation.java @@ -83,4 +83,9 @@ public boolean isOverrideArgs() { protected ClassMatch enhanceClass() { return NameMatch.byName(ENHANCE_CLASS); } + + @Override + protected String[] witnessClasses() { + return new String[]{"org.jboss.resteasy.core.Dispatcher"}; + } } diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v4/server/define/SynchronousDispatcherInstrumentation.java b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v4/server/define/SynchronousDispatcherInstrumentation.java index 245994dc69..206af100d8 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v4/server/define/SynchronousDispatcherInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v4/server/define/SynchronousDispatcherInstrumentation.java @@ -20,13 +20,18 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; 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.NameMatch; +import java.util.Collections; +import java.util.List; + import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; public class SynchronousDispatcherInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { @@ -83,4 +88,17 @@ public boolean isOverrideArgs() { protected ClassMatch enhanceClass() { return NameMatch.byName(ENHANCE_CLASS); } + + @Override + protected String[] witnessClasses() { + return new String[]{"org.jboss.resteasy.core.InternalDispatcher"}; + } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + "org.jboss.resteasy.spi.Dispatcher", + named("internalInvocation").and(returns(named("javax.ws.rs.core.Response"))) + )); + } } diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v6/server/define/SynchronousDispatcherInstrumentation.java b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v6/server/define/SynchronousDispatcherInstrumentation.java index c4a472487c..d38fb5775d 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v6/server/define/SynchronousDispatcherInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/resteasy/v6/server/define/SynchronousDispatcherInstrumentation.java @@ -20,13 +20,18 @@ import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; 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.NameMatch; +import java.util.Collections; +import java.util.List; + import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.returns; import static net.bytebuddy.matcher.ElementMatchers.takesArguments; public class SynchronousDispatcherInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { @@ -83,4 +88,17 @@ public boolean isOverrideArgs() { protected ClassMatch enhanceClass() { return NameMatch.byName(ENHANCE_CLASS); } + + @Override + protected String[] witnessClasses() { + return new String[]{"org.jboss.resteasy.core.InternalDispatcher"}; + } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + "org.jboss.resteasy.spi.Dispatcher", + named("internalInvocation").and(returns(named("jakarta.ws.rs.core.Response"))) + )); + } } From 2027a98b1ec28ec24be3b7aac346d11bb3f3ccfe Mon Sep 17 00:00:00 2001 From: zhengziyi0117 <91662408+zhengziyi0117@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:22:33 +0800 Subject: [PATCH 033/114] Support async profiler feature (#720) --- .../command/AsyncProfilerTaskCommand.java | 133 ++++++++++++ .../command/CommandDeserializer.java | 3 + apm-protocol/apm-network/src/main/proto | 2 +- apm-sniffer/apm-agent-core/pom.xml | 4 + .../AsyncProfilerDataSender.java | 194 ++++++++++++++++++ .../core/asyncprofiler/AsyncProfilerTask.java | 146 +++++++++++++ .../AsyncProfilerTaskChannelService.java | 131 ++++++++++++ .../AsyncProfilerTaskExecutionService.java | 160 +++++++++++++++ .../core/commands/CommandExecutorService.java | 5 + .../AsyncProfilerCommandExecutor.java | 44 ++++ .../apm/agent/core/conf/Config.java | 27 +++ ...skywalking.apm.agent.core.boot.BootService | 3 + .../agent/core/boot/ServiceManagerTest.java | 4 +- apm-sniffer/config/agent.config | 6 + dist-material/LICENSE | 1 + pom.xml | 6 + 16 files changed, 866 insertions(+), 3 deletions(-) create mode 100644 apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/AsyncProfilerTaskCommand.java create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTask.java create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskChannelService.java create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskExecutionService.java create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/commands/executor/AsyncProfilerCommandExecutor.java diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/AsyncProfilerTaskCommand.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/AsyncProfilerTaskCommand.java new file mode 100644 index 0000000000..41d6043dee --- /dev/null +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/AsyncProfilerTaskCommand.java @@ -0,0 +1,133 @@ +/* + * 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.network.trace.component.command; + +import org.apache.skywalking.apm.network.common.v3.Command; +import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair; + +import java.util.List; +import java.util.Objects; + +public class AsyncProfilerTaskCommand extends BaseCommand implements Serializable, Deserializable { + public static final Deserializable DESERIALIZER = new AsyncProfilerTaskCommand("", "", 0, null, "", 0); + public static final String NAME = "AsyncProfilerTaskQuery"; + + /** + * async-profiler taskId + */ + private final String taskId; + /** + * run profiling for duration (second) + */ + private final int duration; + /** + * async profiler extended parameters. Here is a table of optional parameters. + * + *

lock[=DURATION] - profile contended locks overflowing the DURATION ns bucket (default: 10us)

+ *

alloc[=BYTES] - profile allocations with BYTES interval

+ *

interval=N - sampling interval in ns (default: 10'000'000, i.e. 10 ms)

+ *

jstackdepth=N - maximum Java stack depth (default: 2048)

+ *

chunksize=N - approximate size of JFR chunk in bytes (default: 100 MB)

+ *

chunktime=N - duration of JFR chunk in seconds (default: 1 hour)

+ * details @see async-profiler argument + */ + private final String execArgs; + /** + * task create time + */ + private final long createTime; + + public AsyncProfilerTaskCommand(String serialNumber, String taskId, int duration, + List events, String execArgs, long createTime) { + super(NAME, serialNumber); + this.taskId = taskId; + this.duration = duration; + this.createTime = createTime; + String comma = ","; + StringBuilder sb = new StringBuilder(); + if (Objects.nonNull(events) && !events.isEmpty()) { + sb.append("event=") + .append(String.join(comma, events)) + .append(comma); + } + if (execArgs != null && !execArgs.isEmpty()) { + sb.append(execArgs); + } + this.execArgs = sb.toString(); + } + + public AsyncProfilerTaskCommand(String serialNumber, String taskId, int duration, + String execArgs, long createTime) { + super(NAME, serialNumber); + this.taskId = taskId; + this.duration = duration; + this.execArgs = execArgs; + this.createTime = createTime; + } + + @Override + public AsyncProfilerTaskCommand deserialize(Command command) { + final List argsList = command.getArgsList(); + String taskId = null; + int duration = 0; + String execArgs = null; + long createTime = 0; + String serialNumber = null; + for (final KeyStringValuePair pair : argsList) { + if ("SerialNumber".equals(pair.getKey())) { + serialNumber = pair.getValue(); + } else if ("TaskId".equals(pair.getKey())) { + taskId = pair.getValue(); + } else if ("Duration".equals(pair.getKey())) { + duration = Integer.parseInt(pair.getValue()); + } else if ("ExecArgs".equals(pair.getKey())) { + execArgs = pair.getValue(); + } else if ("CreateTime".equals(pair.getKey())) { + createTime = Long.parseLong(pair.getValue()); + } + } + return new AsyncProfilerTaskCommand(serialNumber, taskId, duration, execArgs, createTime); + } + + @Override + public Command.Builder serialize() { + final Command.Builder builder = commandBuilder(); + builder.addArgs(KeyStringValuePair.newBuilder().setKey("TaskId").setValue(taskId)) + .addArgs(KeyStringValuePair.newBuilder().setKey("Duration").setValue(String.valueOf(duration))) + .addArgs(KeyStringValuePair.newBuilder().setKey("ExecArgs").setValue(execArgs)) + .addArgs(KeyStringValuePair.newBuilder().setKey("CreateTime").setValue(String.valueOf(createTime))); + return builder; + } + + public String getTaskId() { + return taskId; + } + + public int getDuration() { + return duration; + } + + public String getExecArgs() { + return execArgs; + } + + public long getCreateTime() { + return createTime; + } +} diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java index ff8680bcb3..4fd737ff98 100644 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/command/CommandDeserializer.java @@ -27,7 +27,10 @@ public static BaseCommand deserialize(final Command command) { return ProfileTaskCommand.DESERIALIZER.deserialize(command); } else if (ConfigurationDiscoveryCommand.NAME.equals(commandName)) { return ConfigurationDiscoveryCommand.DESERIALIZER.deserialize(command); + } else if (AsyncProfilerTaskCommand.NAME.equals(commandName)) { + return AsyncProfilerTaskCommand.DESERIALIZER.deserialize(command); } + throw new UnsupportedCommandException(command); } diff --git a/apm-protocol/apm-network/src/main/proto b/apm-protocol/apm-network/src/main/proto index d4da569991..bd1f91f7e1 160000 --- a/apm-protocol/apm-network/src/main/proto +++ b/apm-protocol/apm-network/src/main/proto @@ -1 +1 @@ -Subproject commit d4da5699915ee52288f8ff1c954decf6363485bc +Subproject commit bd1f91f7e1cb4de9d9b5ccb71f36ce6b1c7c97f5 diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index 8ba309156f..fcca095f25 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -143,6 +143,10 @@ jmh-generator-annprocess test + + tools.profiler + async-profiler + diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java new file mode 100644 index 0000000000..5e09fab5b0 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java @@ -0,0 +1,194 @@ +/* + * 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.agent.core.asyncprofiler; + +import com.google.protobuf.ByteString; +import io.grpc.Channel; +import io.grpc.stub.ClientCallStreamObserver; +import io.grpc.stub.ClientResponseObserver; +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.apm.agent.core.boot.BootService; +import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.conf.Config; +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.agent.core.remote.GRPCChannelListener; +import org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager; +import org.apache.skywalking.apm.agent.core.remote.GRPCChannelStatus; +import org.apache.skywalking.apm.agent.core.remote.GRPCStreamServiceStatus; +import org.apache.skywalking.apm.network.language.asyncprofiler.v10.AsyncProfilerCollectionResponse; +import org.apache.skywalking.apm.network.language.asyncprofiler.v10.AsyncProfilerData; +import org.apache.skywalking.apm.network.language.asyncprofiler.v10.AsyncProfilerMetaData; +import org.apache.skywalking.apm.network.language.asyncprofiler.v10.AsyncProfilerTaskGrpc; +import org.apache.skywalking.apm.network.language.asyncprofiler.v10.AsyncProfilingStatus; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static org.apache.skywalking.apm.agent.core.conf.Config.AsyncProfiler.DATA_CHUNK_SIZE; +import static org.apache.skywalking.apm.agent.core.conf.Config.Collector.GRPC_UPSTREAM_TIMEOUT; + +@DefaultImplementor +public class AsyncProfilerDataSender implements BootService, GRPCChannelListener { + private static final ILog LOGGER = LogManager.getLogger(AsyncProfilerDataSender.class); + + private volatile GRPCChannelStatus status = GRPCChannelStatus.DISCONNECT; + + private volatile AsyncProfilerTaskGrpc.AsyncProfilerTaskStub asyncProfilerTaskStub; + + @Override + public void prepare() throws Throwable { + ServiceManager.INSTANCE.findService(GRPCChannelManager.class).addChannelListener(this); + } + + @Override + public void boot() throws Throwable { + + } + + @Override + public void onComplete() throws Throwable { + + } + + @Override + public void shutdown() throws Throwable { + + } + + @Override + public void statusChanged(GRPCChannelStatus status) { + if (GRPCChannelStatus.CONNECTED.equals(status)) { + Channel channel = ServiceManager.INSTANCE.findService(GRPCChannelManager.class).getChannel(); + asyncProfilerTaskStub = AsyncProfilerTaskGrpc.newStub(channel); + } else { + asyncProfilerTaskStub = null; + } + this.status = status; + } + + public void sendData(AsyncProfilerTask task, FileChannel channel) throws IOException, InterruptedException { + if (status != GRPCChannelStatus.CONNECTED || Objects.isNull(channel) || !channel.isOpen()) { + return; + } + + int size = Math.toIntExact(channel.size()); + final GRPCStreamServiceStatus status = new GRPCStreamServiceStatus(false); + StreamObserver dataStreamObserver = asyncProfilerTaskStub.withDeadlineAfter( + GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS + ).collect(new ClientResponseObserver() { + ClientCallStreamObserver requestStream; + + @Override + public void beforeStart(ClientCallStreamObserver requestStream) { + this.requestStream = requestStream; + } + + @Override + public void onNext(AsyncProfilerCollectionResponse value) { + if (AsyncProfilingStatus.TERMINATED_BY_OVERSIZE.equals(value.getType())) { + LOGGER.warn("JFR is too large to be received by the oap server"); + } else { + ByteBuffer buf = ByteBuffer.allocateDirect(DATA_CHUNK_SIZE); + try { + while (channel.read(buf) > 0) { + buf.flip(); + AsyncProfilerData asyncProfilerData = AsyncProfilerData.newBuilder() + .setContent(ByteString.copyFrom(buf)) + .build(); + requestStream.onNext(asyncProfilerData); + buf.clear(); + } + } catch (IOException e) { + LOGGER.error("Failed to read JFR file and failed to upload to oap", e); + } + } + + requestStream.onCompleted(); + } + + @Override + public void onError(Throwable t) { + status.finished(); + LOGGER.error(t, "Send async profiler task data to collector fail with a grpc internal exception."); + ServiceManager.INSTANCE.findService(GRPCChannelManager.class).reportError(t); + } + + @Override + public void onCompleted() { + status.finished(); + } + }); + AsyncProfilerMetaData metaData = AsyncProfilerMetaData.newBuilder() + .setService(Config.Agent.SERVICE_NAME) + .setServiceInstance(Config.Agent.INSTANCE_NAME) + .setType(AsyncProfilingStatus.PROFILING_SUCCESS) + .setContentSize(size) + .setTaskId(task.getTaskId()) + .build(); + AsyncProfilerData asyncProfilerData = AsyncProfilerData.newBuilder().setMetaData(metaData).build(); + dataStreamObserver.onNext(asyncProfilerData); + + status.wait4Finish(); + } + + public void sendError(AsyncProfilerTask task, String errorMessage) { + if (status != GRPCChannelStatus.CONNECTED) { + return; + } + final GRPCStreamServiceStatus status = new GRPCStreamServiceStatus(false); + StreamObserver dataStreamObserver = asyncProfilerTaskStub.withDeadlineAfter( + GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS + ).collect(new StreamObserver() { + @Override + public void onNext(AsyncProfilerCollectionResponse value) { + } + + @Override + public void onError(Throwable t) { + status.finished(); + LOGGER.error(t, "Send async profiler task execute error fail with a grpc internal exception."); + ServiceManager.INSTANCE.findService(GRPCChannelManager.class).reportError(t); + } + + @Override + public void onCompleted() { + status.finished(); + } + }); + AsyncProfilerMetaData metaData = AsyncProfilerMetaData.newBuilder() + .setService(Config.Agent.SERVICE_NAME) + .setServiceInstance(Config.Agent.INSTANCE_NAME) + .setTaskId(task.getTaskId()) + .setType(AsyncProfilingStatus.EXECUTION_TASK_ERROR) + .setContentSize(-1) + .build(); + AsyncProfilerData asyncProfilerData = AsyncProfilerData.newBuilder() + .setMetaData(metaData) + .setErrorMessage(errorMessage) + .build(); + dataStreamObserver.onNext(asyncProfilerData); + dataStreamObserver.onCompleted(); + status.wait4Finish(); + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTask.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTask.java new file mode 100644 index 0000000000..95948762b2 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTask.java @@ -0,0 +1,146 @@ +/* + * 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.agent.core.asyncprofiler; + +import one.profiler.AsyncProfiler; +import org.apache.skywalking.apm.agent.core.conf.Config; +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.util.StringUtil; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class AsyncProfilerTask { + private static final ILog LOGGER = LogManager.getLogger(AsyncProfilerTask.class); + private static final String COMMA = ","; + /** + * task id + */ + private String taskId; + /** + * async profiler optional extended parameters + * + * @see org.apache.skywalking.apm.network.trace.component.command.AsyncProfilerTaskCommand + */ + private String execArgs; + /** + * run profiling for duration (second) + */ + private int duration; + /** + * The time when oap server created this task + */ + private long createTime; + /** + * tempFile generated by async-profiler execution + */ + private Path tempFile; + + private static String execute(AsyncProfiler asyncProfiler, String args) + throws IllegalArgumentException, IOException { + LOGGER.info("async profiler execute args:{}", args); + return asyncProfiler.execute(args); + } + + /** + * start async profiler + */ + public String start(AsyncProfiler asyncProfiler) throws IOException { + tempFile = getProfilerFilePath(); + StringBuilder startArgs = new StringBuilder(); + startArgs.append("start").append(COMMA); + if (StringUtil.isNotEmpty(execArgs)) { + startArgs.append(execArgs).append(COMMA); + } + startArgs.append("file=").append(tempFile.toString()); + + return execute(asyncProfiler, startArgs.toString()); + } + + /** + * stop async profiler and get file + */ + public File stop(AsyncProfiler asyncProfiler) throws IOException { + LOGGER.info("async profiler process stop and dump file"); + String stopArgs = "stop" + COMMA + "file=" + tempFile.toAbsolutePath(); + execute(asyncProfiler, stopArgs); + return tempFile.toFile(); + } + + /** + * if outputPath is configured, the JFR file will be generated at outputPath, + * otherwise createTemp will be used to create the file + */ + public Path getProfilerFilePath() throws IOException { + if (StringUtil.isNotEmpty(Config.AsyncProfiler.OUTPUT_PATH)) { + Path tempFilePath = Paths.get(Config.AsyncProfiler.OUTPUT_PATH, taskId + getFileExtension()); + return Files.createFile(tempFilePath.toAbsolutePath()); + } else { + return Files.createTempFile(taskId, getFileExtension()); + } + } + + private String getFileExtension() { + return ".jfr"; + } + + public void setExecArgs(String execArgs) { + this.execArgs = execArgs; + } + + public void setDuration(int duration) { + this.duration = duration; + } + + public void setTempFile(Path tempFile) { + this.tempFile = tempFile; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + + public String getExecArgs() { + return execArgs; + } + + public int getDuration() { + return duration; + } + + public Path getTempFile() { + return tempFile; + } + + public String getTaskId() { + return taskId; + } + + public long getCreateTime() { + return createTime; + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskChannelService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskChannelService.java new file mode 100644 index 0000000000..7a2b26a46a --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskChannelService.java @@ -0,0 +1,131 @@ +/* + * 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.agent.core.asyncprofiler; + +import io.grpc.Channel; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; +import org.apache.skywalking.apm.agent.core.boot.BootService; +import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor; +import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.commands.CommandService; +import org.apache.skywalking.apm.agent.core.conf.Config; +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.agent.core.remote.GRPCChannelListener; +import org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager; +import org.apache.skywalking.apm.agent.core.remote.GRPCChannelStatus; +import org.apache.skywalking.apm.network.common.v3.Commands; +import org.apache.skywalking.apm.network.language.asyncprofiler.v10.AsyncProfilerTaskCommandQuery; +import org.apache.skywalking.apm.network.language.asyncprofiler.v10.AsyncProfilerTaskGrpc; +import org.apache.skywalking.apm.util.RunnableWithExceptionProtection; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import static org.apache.skywalking.apm.agent.core.conf.Config.Collector.GRPC_UPSTREAM_TIMEOUT; + +@DefaultImplementor +public class AsyncProfilerTaskChannelService implements BootService, Runnable, GRPCChannelListener { + private static final ILog LOGGER = LogManager.getLogger(AsyncProfilerTaskChannelService.class); + + // channel status + private volatile GRPCChannelStatus status = GRPCChannelStatus.DISCONNECT; + private volatile AsyncProfilerTaskGrpc.AsyncProfilerTaskBlockingStub asyncProfilerTaskBlockingStub; + + // query task schedule + private volatile ScheduledFuture getTaskFuture; + + @Override + public void run() { + if (status == GRPCChannelStatus.CONNECTED) { + try { + // test start command and 10s after put stop command + long lastCommandCreateTime = ServiceManager.INSTANCE + .findService(AsyncProfilerTaskExecutionService.class).getLastCommandCreateTime(); + + AsyncProfilerTaskCommandQuery query = AsyncProfilerTaskCommandQuery.newBuilder() + .setServiceInstance(Config.Agent.INSTANCE_NAME) + .setService(Config.Agent.SERVICE_NAME) + .setLastCommandTime(lastCommandCreateTime) + .build(); + Commands commands = asyncProfilerTaskBlockingStub.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS) + .getAsyncProfilerTaskCommands(query); + ServiceManager.INSTANCE.findService(CommandService.class).receiveCommand(commands); + } catch (Throwable t) { + if (!(t instanceof StatusRuntimeException)) { + LOGGER.error(t, "fail to query async-profiler task from backend"); + return; + } + final StatusRuntimeException statusRuntimeException = (StatusRuntimeException) t; + if (Status.Code.UNIMPLEMENTED.equals(statusRuntimeException.getStatus().getCode())) { + LOGGER.warn("Backend doesn't support async-profiler, async-profiler will be disabled"); + if (getTaskFuture != null) { + getTaskFuture.cancel(true); + } + } + } + } + } + + @Override + public void statusChanged(GRPCChannelStatus status) { + if (GRPCChannelStatus.CONNECTED.equals(status)) { + Channel channel = ServiceManager.INSTANCE.findService(GRPCChannelManager.class).getChannel(); + asyncProfilerTaskBlockingStub = AsyncProfilerTaskGrpc.newBlockingStub(channel); + } else { + asyncProfilerTaskBlockingStub = null; + } + this.status = status; + } + + @Override + public void prepare() throws Throwable { + ServiceManager.INSTANCE.findService(GRPCChannelManager.class).addChannelListener(this); + } + + @Override + public void boot() throws Throwable { + + if (Config.AsyncProfiler.ACTIVE) { + getTaskFuture = Executors.newSingleThreadScheduledExecutor( + new DefaultNamedThreadFactory("AsyncProfilerGetTaskService") + ).scheduleWithFixedDelay( + new RunnableWithExceptionProtection( + this, + t -> LOGGER.error("Query async profiler task list failure.", t) + ), 0, Config.Collector.GET_PROFILE_TASK_INTERVAL, TimeUnit.SECONDS + ); + } + } + + @Override + public void onComplete() throws Throwable { + + } + + @Override + public void shutdown() throws Throwable { + if (getTaskFuture != null) { + getTaskFuture.cancel(true); + } + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskExecutionService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskExecutionService.java new file mode 100644 index 0000000000..550923c1b0 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskExecutionService.java @@ -0,0 +1,160 @@ +/* + * 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.agent.core.asyncprofiler; + +import one.profiler.AsyncProfiler; +import org.apache.skywalking.apm.agent.core.boot.BootService; +import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor; +import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.util.Objects; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +@DefaultImplementor +public class AsyncProfilerTaskExecutionService implements BootService { + + private static final ILog LOGGER = LogManager.getLogger(AsyncProfilerTaskChannelService.class); + + private AsyncProfiler asyncProfilerInstance; + + private static final String SUCCESS_RESULT = "Profiling started\n"; + + // profile executor thread pool, only running one thread + private volatile ScheduledExecutorService asyncProfilerExecutor; + + // last command create time, use to next query task list + private volatile long lastCommandCreateTime = -1; + + // task schedule future + private volatile ScheduledFuture scheduledFuture; + + public void processAsyncProfilerTask(AsyncProfilerTask task) { + if (task.getCreateTime() <= lastCommandCreateTime) { + LOGGER.warn("get repeat task because createTime is less than lastCommandCreateTime"); + return; + } + lastCommandCreateTime = task.getCreateTime(); + LOGGER.info("add async profiler task: {}", task.getTaskId()); + // add task to list + getAsyncProfilerExecutor().execute(() -> { + try { + if (Objects.nonNull(scheduledFuture) && !scheduledFuture.isDone()) { + LOGGER.info("AsyncProfilerTask already running"); + return; + } + + String result = task.start(getAsyncProfiler()); + if (!SUCCESS_RESULT.equals(result)) { + stopWhenError(task, result); + return; + } + scheduledFuture = getAsyncProfilerExecutor().schedule( + () -> stopWhenSuccess(task), task.getDuration(), TimeUnit.SECONDS + ); + } catch (IOException e) { + LOGGER.error("AsyncProfilerTask executor error:" + e.getMessage(), e); + } + }); + } + + private void stopWhenError(AsyncProfilerTask task, String errorMessage) { + LOGGER.error("AsyncProfilerTask fails to start: " + errorMessage); + AsyncProfilerDataSender dataSender = ServiceManager.INSTANCE.findService(AsyncProfilerDataSender.class); + dataSender.sendError(task, errorMessage); + } + + private void stopWhenSuccess(AsyncProfilerTask task) { + + try { + File dumpFile = task.stop(getAsyncProfiler()); + // stop task + try (FileInputStream fileInputStream = new FileInputStream(dumpFile)) { + // upload file + FileChannel channel = fileInputStream.getChannel(); + + AsyncProfilerDataSender dataSender = ServiceManager.INSTANCE.findService(AsyncProfilerDataSender.class); + dataSender.sendData(task, channel); + } + + if (!dumpFile.delete()) { + LOGGER.warn("Fail to delete the dump file of async profiler."); + } + } catch (Exception e) { + LOGGER.error("stop async profiler task error", e); + return; + } + } + + public long getLastCommandCreateTime() { + return lastCommandCreateTime; + } + + @Override + public void prepare() throws Throwable { + + } + + @Override + public void boot() throws Throwable { + + } + + @Override + public void onComplete() throws Throwable { + + } + + @Override + public void shutdown() throws Throwable { + getAsyncProfilerExecutor().shutdown(); + if (Objects.nonNull(scheduledFuture)) { + scheduledFuture.cancel(true); + scheduledFuture = null; + } + } + + private AsyncProfiler getAsyncProfiler() { + if (asyncProfilerInstance == null) { + asyncProfilerInstance = AsyncProfiler.getInstance(); + } + return asyncProfilerInstance; + } + + private ScheduledExecutorService getAsyncProfilerExecutor() { + if (asyncProfilerExecutor == null) { + synchronized (this) { + if (asyncProfilerExecutor == null) { + asyncProfilerExecutor = Executors.newSingleThreadScheduledExecutor( + new DefaultNamedThreadFactory("ASYNC-PROFILING-TASK")); + } + } + } + return asyncProfilerExecutor; + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/commands/CommandExecutorService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/commands/CommandExecutorService.java index 819b0b9ff1..c619051c9b 100755 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/commands/CommandExecutorService.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/commands/CommandExecutorService.java @@ -21,9 +21,11 @@ import java.util.Map; import org.apache.skywalking.apm.agent.core.boot.BootService; import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor; +import org.apache.skywalking.apm.agent.core.commands.executor.AsyncProfilerCommandExecutor; import org.apache.skywalking.apm.agent.core.commands.executor.ConfigurationDiscoveryCommandExecutor; import org.apache.skywalking.apm.agent.core.commands.executor.NoopCommandExecutor; import org.apache.skywalking.apm.agent.core.commands.executor.ProfileTaskCommandExecutor; +import org.apache.skywalking.apm.network.trace.component.command.AsyncProfilerTaskCommand; import org.apache.skywalking.apm.network.trace.component.command.BaseCommand; import org.apache.skywalking.apm.network.trace.component.command.ConfigurationDiscoveryCommand; import org.apache.skywalking.apm.network.trace.component.command.ProfileTaskCommand; @@ -48,6 +50,9 @@ public void prepare() throws Throwable { //Get ConfigurationDiscoveryCommand executor. commandExecutorMap.put(ConfigurationDiscoveryCommand.NAME, new ConfigurationDiscoveryCommandExecutor()); + + // AsyncProfiler task executor + commandExecutorMap.put(AsyncProfilerTaskCommand.NAME, new AsyncProfilerCommandExecutor()); } @Override diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/commands/executor/AsyncProfilerCommandExecutor.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/commands/executor/AsyncProfilerCommandExecutor.java new file mode 100644 index 0000000000..530b655f84 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/commands/executor/AsyncProfilerCommandExecutor.java @@ -0,0 +1,44 @@ +/* + * 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.agent.core.commands.executor; + +import org.apache.skywalking.apm.agent.core.asyncprofiler.AsyncProfilerTask; +import org.apache.skywalking.apm.agent.core.asyncprofiler.AsyncProfilerTaskExecutionService; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.commands.CommandExecutionException; +import org.apache.skywalking.apm.agent.core.commands.CommandExecutor; +import org.apache.skywalking.apm.agent.core.conf.Config; +import org.apache.skywalking.apm.network.trace.component.command.AsyncProfilerTaskCommand; +import org.apache.skywalking.apm.network.trace.component.command.BaseCommand; + +public class AsyncProfilerCommandExecutor implements CommandExecutor { + @Override + public void execute(BaseCommand command) throws CommandExecutionException { + AsyncProfilerTaskCommand asyncProfilerTaskCommand = (AsyncProfilerTaskCommand) command; + + AsyncProfilerTask asyncProfilerTask = new AsyncProfilerTask(); + asyncProfilerTask.setTaskId(asyncProfilerTaskCommand.getTaskId()); + int duration = Math.min(Config.AsyncProfiler.MAX_DURATION, asyncProfilerTaskCommand.getDuration()); + asyncProfilerTask.setDuration(duration); + asyncProfilerTask.setExecArgs(asyncProfilerTaskCommand.getExecArgs()); + asyncProfilerTask.setCreateTime(asyncProfilerTaskCommand.getCreateTime()); + ServiceManager.INSTANCE.findService(AsyncProfilerTaskExecutionService.class) + .processAsyncProfilerTask(asyncProfilerTask); + } +} diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java index be7d54a4e4..fe2b7448e1 100755 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java @@ -252,6 +252,33 @@ public static class Profile { public static int SNAPSHOT_TRANSPORT_BUFFER_SIZE = 500; } + public static class AsyncProfiler { + /** + * If true, async profiler will be enabled when user creates a new async profiler task. + * If false, it will be disabled. + * The default value is true. + */ + public static boolean ACTIVE = true; + + /** + * Max execution time(second) for the Async Profiler. The task will be stopped even if a longer time is specified. + * default 10min. + */ + public static int MAX_DURATION = 600; + + /** + * Path for the JFR outputs from the Async Profiler. + * If the parameter is not empty, the file will be created in the specified directory, + * otherwise the Files.createTemp method will be used to create the file. + */ + public static String OUTPUT_PATH = ""; + + /** + * The size of the chunk when uploading jfr + */ + public static final int DATA_CHUNK_SIZE = 1024 * 1024; + } + public static class Meter { /** * If true, skywalking agent will enable sending meters. Otherwise disable meter report. diff --git a/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService b/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService index cfda93521c..f75d28cd78 100644 --- a/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService +++ b/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService @@ -36,3 +36,6 @@ org.apache.skywalking.apm.agent.core.remote.LogReportServiceClient org.apache.skywalking.apm.agent.core.conf.dynamic.ConfigurationDiscoveryService org.apache.skywalking.apm.agent.core.remote.EventReportServiceClient org.apache.skywalking.apm.agent.core.ServiceInstanceGenerator +org.apache.skywalking.apm.agent.core.asyncprofiler.AsyncProfilerTaskExecutionService +org.apache.skywalking.apm.agent.core.asyncprofiler.AsyncProfilerTaskChannelService +org.apache.skywalking.apm.agent.core.asyncprofiler.AsyncProfilerDataSender \ No newline at end of file diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerTest.java index 48af242a43..e177920cfe 100644 --- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerTest.java +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerTest.java @@ -59,7 +59,7 @@ public static void afterClass() { public void testServiceDependencies() throws Exception { HashMap registryService = getFieldValue(ServiceManager.INSTANCE, "bootedServices"); - assertThat(registryService.size(), is(20)); + assertThat(registryService.size(), is(23)); assertTraceSegmentServiceClient(ServiceManager.INSTANCE.findService(TraceSegmentServiceClient.class)); assertContextManager(ServiceManager.INSTANCE.findService(ContextManager.class)); @@ -109,7 +109,7 @@ private void assertGRPCChannelManager(GRPCChannelManager service) throws Excepti assertNotNull(service); List listeners = getFieldValue(service, "listeners"); - assertEquals(listeners.size(), 10); + assertEquals(listeners.size(), 12); } private void assertSamplingService(SamplingService service) { diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index 06f5717de0..0ceb658627 100755 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -164,6 +164,12 @@ profile.duration=${SW_AGENT_PROFILE_DURATION:10} profile.dump_max_stack_depth=${SW_AGENT_PROFILE_DUMP_MAX_STACK_DEPTH:500} # Snapshot transport to backend buffer size profile.snapshot_transport_buffer_size=${SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE:4500} +# If true, async profiler will be enabled when user creates a new async profiler task. If false, it will be disabled. The default value is true. +asyncprofiler.active=${SW_AGENT_ASYNC_PROFILER_ACTIVE:true} +# Max execution time(second) for the Async Profiler. The task will be stopped even if a longer time is specified. default 10min. +asyncprofiler.max_duration=${SW_AGENT_ASYNC_PROFILER_MAX_DURATION:600} +# Path for the JFR outputs from the Async Profiler. If the parameter is not empty, the file will be created in the specified directory, otherwise the Files.createTemp method will be used to create the file. +asyncprofiler.output_path=${SW_AGENT_ASYNC_PROFILER_OUTPUT_PATH:} # If true, the agent collects and reports metrics to the backend. meter.active=${SW_METER_ACTIVE:true} # Report meters interval. The unit is second diff --git a/dist-material/LICENSE b/dist-material/LICENSE index a5c6f781cf..f36ccd2177 100755 --- a/dist-material/LICENSE +++ b/dist-material/LICENSE @@ -222,6 +222,7 @@ The text of each license is the standard Apache 2.0 license. Google: jsr305 3.0.2: http://central.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.0/jsr305-3.0.0.pom , Apache 2.0 Google: guava 32.0.1: https://github.com/google/guava , Apache 2.0 netty 4.1.100: https://github.com/netty/netty/blob/4.1/LICENSE.txt, Apache 2.0 + async-profiler 3.0: https://github.com/async-profiler/async-profiler/blob/v3.0/LICENSE, Apache 2.0 ======================================================================== BSD licenses diff --git a/pom.xml b/pom.xml index adac36458d..1ca1ec9c2a 100755 --- a/pom.xml +++ b/pom.xml @@ -97,6 +97,7 @@ 2.0.48.Final 1.3.2 3.1 + 3.0 6.0.53 @@ -260,6 +261,11 @@ ${jmh.version} test + + tools.profiler + async-profiler + ${async-profiler.version} + From 54a3372a8fdbfe562659cbee6f679839f1b88ec2 Mon Sep 17 00:00:00 2001 From: zhengziyi0117 <91662408+zhengziyi0117@users.noreply.github.com> Date: Wed, 30 Oct 2024 18:52:56 +0800 Subject: [PATCH 034/114] Add async-profiler feature CHANGES.md (#724) --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 270c4ab125..c2c322b280 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ Release Notes. * Add agent self-observability. * Fix intermittent ClassCircularityError by preloading ThreadLocalRandom since ByteBuddy 1.12.11 * Add witness class/method for resteasy-server plugin(v3/v4/v6) +* Add async-profiler feature for performance analysis All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) From 26e59485ccd5298f243af9f91f3ff60c0eb80586 Mon Sep 17 00:00:00 2001 From: zhengziyi0117 <91662408+zhengziyi0117@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:31:33 +0800 Subject: [PATCH 035/114] fix: jdk8 send jfr data error (#725) --- .../AsyncProfilerDataSender.java | 116 +++++++++--------- .../AsyncProfilerTaskExecutionService.java | 19 +-- 2 files changed, 65 insertions(+), 70 deletions(-) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java index 5e09fab5b0..46a25c4cc2 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java @@ -39,10 +39,10 @@ import org.apache.skywalking.apm.network.language.asyncprofiler.v10.AsyncProfilerTaskGrpc; import org.apache.skywalking.apm.network.language.asyncprofiler.v10.AsyncProfilingStatus; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.Objects; +import java.nio.file.Files; import java.util.concurrent.TimeUnit; import static org.apache.skywalking.apm.agent.core.conf.Config.AsyncProfiler.DATA_CHUNK_SIZE; @@ -87,69 +87,71 @@ public void statusChanged(GRPCChannelStatus status) { this.status = status; } - public void sendData(AsyncProfilerTask task, FileChannel channel) throws IOException, InterruptedException { - if (status != GRPCChannelStatus.CONNECTED || Objects.isNull(channel) || !channel.isOpen()) { + public void sendData(AsyncProfilerTask task, File dumpFile) throws IOException, InterruptedException { + if (status != GRPCChannelStatus.CONNECTED) { return; } - int size = Math.toIntExact(channel.size()); - final GRPCStreamServiceStatus status = new GRPCStreamServiceStatus(false); - StreamObserver dataStreamObserver = asyncProfilerTaskStub.withDeadlineAfter( - GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS - ).collect(new ClientResponseObserver() { - ClientCallStreamObserver requestStream; - - @Override - public void beforeStart(ClientCallStreamObserver requestStream) { - this.requestStream = requestStream; - } + try (FileInputStream fileInputStream = new FileInputStream(dumpFile)) { + long fileSize = Files.size(dumpFile.toPath()); + int size = Math.toIntExact(fileSize); + final GRPCStreamServiceStatus status = new GRPCStreamServiceStatus(false); + StreamObserver dataStreamObserver = asyncProfilerTaskStub.withDeadlineAfter( + GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS + ).collect(new ClientResponseObserver() { + ClientCallStreamObserver requestStream; + + @Override + public void beforeStart(ClientCallStreamObserver requestStream) { + this.requestStream = requestStream; + } - @Override - public void onNext(AsyncProfilerCollectionResponse value) { - if (AsyncProfilingStatus.TERMINATED_BY_OVERSIZE.equals(value.getType())) { - LOGGER.warn("JFR is too large to be received by the oap server"); - } else { - ByteBuffer buf = ByteBuffer.allocateDirect(DATA_CHUNK_SIZE); - try { - while (channel.read(buf) > 0) { - buf.flip(); - AsyncProfilerData asyncProfilerData = AsyncProfilerData.newBuilder() - .setContent(ByteString.copyFrom(buf)) - .build(); - requestStream.onNext(asyncProfilerData); - buf.clear(); + @Override + public void onNext(AsyncProfilerCollectionResponse value) { + if (AsyncProfilingStatus.TERMINATED_BY_OVERSIZE.equals(value.getType())) { + LOGGER.warn("JFR is too large to be received by the oap server"); + } else { + byte[] buf = new byte[DATA_CHUNK_SIZE]; + try { + int bytesRead; + while ((bytesRead = fileInputStream.read(buf)) != -1) { + AsyncProfilerData asyncProfilerData = AsyncProfilerData.newBuilder() + .setContent(ByteString.copyFrom(buf, 0, bytesRead)) + .build(); + requestStream.onNext(asyncProfilerData); + } + } catch (IOException e) { + LOGGER.error("Failed to read JFR file and failed to upload to oap", e); } - } catch (IOException e) { - LOGGER.error("Failed to read JFR file and failed to upload to oap", e); } - } - - requestStream.onCompleted(); - } - @Override - public void onError(Throwable t) { - status.finished(); - LOGGER.error(t, "Send async profiler task data to collector fail with a grpc internal exception."); - ServiceManager.INSTANCE.findService(GRPCChannelManager.class).reportError(t); - } + requestStream.onCompleted(); + } - @Override - public void onCompleted() { - status.finished(); - } - }); - AsyncProfilerMetaData metaData = AsyncProfilerMetaData.newBuilder() - .setService(Config.Agent.SERVICE_NAME) - .setServiceInstance(Config.Agent.INSTANCE_NAME) - .setType(AsyncProfilingStatus.PROFILING_SUCCESS) - .setContentSize(size) - .setTaskId(task.getTaskId()) - .build(); - AsyncProfilerData asyncProfilerData = AsyncProfilerData.newBuilder().setMetaData(metaData).build(); - dataStreamObserver.onNext(asyncProfilerData); + @Override + public void onError(Throwable t) { + status.finished(); + LOGGER.error(t, "Send async profiler task data to collector fail with a grpc internal exception."); + ServiceManager.INSTANCE.findService(GRPCChannelManager.class).reportError(t); + } - status.wait4Finish(); + @Override + public void onCompleted() { + status.finished(); + } + }); + AsyncProfilerMetaData metaData = AsyncProfilerMetaData.newBuilder() + .setService(Config.Agent.SERVICE_NAME) + .setServiceInstance(Config.Agent.INSTANCE_NAME) + .setType(AsyncProfilingStatus.PROFILING_SUCCESS) + .setContentSize(size) + .setTaskId(task.getTaskId()) + .build(); + AsyncProfilerData asyncProfilerData = AsyncProfilerData.newBuilder().setMetaData(metaData).build(); + dataStreamObserver.onNext(asyncProfilerData); + + status.wait4Finish(); + } } public void sendError(AsyncProfilerTask task, String errorMessage) { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskExecutionService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskExecutionService.java index 550923c1b0..b5d7a5b643 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskExecutionService.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerTaskExecutionService.java @@ -27,9 +27,7 @@ import org.apache.skywalking.apm.agent.core.logging.api.LogManager; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.nio.channels.FileChannel; import java.util.Objects; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -90,20 +88,15 @@ private void stopWhenError(AsyncProfilerTask task, String errorMessage) { } private void stopWhenSuccess(AsyncProfilerTask task) { - + // stop task and send data try { File dumpFile = task.stop(getAsyncProfiler()); - // stop task - try (FileInputStream fileInputStream = new FileInputStream(dumpFile)) { - // upload file - FileChannel channel = fileInputStream.getChannel(); - + if (dumpFile != null && dumpFile.exists()) { AsyncProfilerDataSender dataSender = ServiceManager.INSTANCE.findService(AsyncProfilerDataSender.class); - dataSender.sendData(task, channel); - } - - if (!dumpFile.delete()) { - LOGGER.warn("Fail to delete the dump file of async profiler."); + dataSender.sendData(task, dumpFile); + if (!dumpFile.delete()) { + LOGGER.warn("Fail to delete the dump file of async profiler."); + } } } catch (Exception e) { LOGGER.error("stop async profiler task error", e); From f0245864e4388a388fe7445b56b6ce7cedc94aaf Mon Sep 17 00:00:00 2001 From: zhengziyi0117 <91662408+zhengziyi0117@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:25:16 +0800 Subject: [PATCH 036/114] fix: shade async-profiler packages (#727) --- apm-sniffer/apm-agent-core/pom.xml | 6 ++++++ apm-sniffer/apm-agent/pom.xml | 1 + 2 files changed, 7 insertions(+) diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index fcca095f25..b22c082035 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -53,6 +53,8 @@ ${shade.package}.${shade.org.slf4j.source} 1.18.0 1.7.25 + one.profiler + ${shade.package}.${shade.one.profiler.source}
@@ -253,6 +255,10 @@ ${shade.org.slf4j.source} ${shade.org.slf4j.target} + + ${shade.one.profiler.source} + ${shade.one.profiler.target} + diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 5f7246b372..0112c21e1c 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -92,6 +92,7 @@ org.codehaus.mojo:animal-sniffer-annotations io.perfmark:* org.slf4j:* + tools.profiler:async-profiler From 860c93c3c1b397006b185ff992d1e0d7af116b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Wed, 27 Nov 2024 10:26:15 +0800 Subject: [PATCH 037/114] Fix deadlinks (#729) --- .dlc.json | 3 +++ .../service-agent/java-agent/Java-Plugin-Development-Guide.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.dlc.json b/.dlc.json index 6a207d2c58..168494a4c4 100644 --- a/.dlc.json +++ b/.dlc.json @@ -26,6 +26,9 @@ }, { "pattern": "^https://twitter.com*" + }, + { + "pattern": "^https://blogs.oracle.com/javamagazine/post/a-peek-into-java-17-continuing-the-drive-to-encapsulate-the-java-runtime-internals" } ], "timeout": "10s", diff --git a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md index 2aa6d148c3..0498f2011d 100644 --- a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md +++ b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md @@ -11,7 +11,7 @@ We also provide the [plugin test tool](#plugin-test-tool) to verify the data col ## Concepts ### Span The span is an important and recognized concept in the distributed tracing system. Learn about the **span** from the -[Google Dapper Paper](https://research.google.com/pubs/pub36356.html) and +[Google Dapper Paper](https://research.google/pubs/dapper-a-large-scale-distributed-systems-tracing-infrastructure/) and [OpenTracing](http://opentracing.io) SkyWalking has supported OpenTracing and OpenTracing-Java API since 2017. Our concepts of the span are similar to that of the Google Dapper Paper and OpenTracing. We have also extended the span. From fc86413aae2fd52577e7e9d7e19b19dbab67171d Mon Sep 17 00:00:00 2001 From: youjie23 <350193107@qq.com> Date: Thu, 28 Nov 2024 13:20:50 +0800 Subject: [PATCH 038/114] =?UTF-8?q?Support=20mongo=20``db.instance``=20tag?= =?UTF-8?q?=E3=80=81``db.collection``=20tag=20and=20``AggregateOperation``?= =?UTF-8?q?=20span=20in=20mongodb-3.x-plugin=20and=20mongodb-4.x-plugin=20?= =?UTF-8?q?(#728)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES.md | 1 + ...regateExplainOperationInstrumentation.java | 64 +++++++ ...AggregateOperationImplInstrumentation.java | 64 +++++++ .../AggregateOperationInstrumentation.java | 64 +++++++ .../ChangeStreamOperationInstrumentation.java | 65 +++++++ .../CommandReadOperationInstrumentation.java | 65 +++++++ .../CountOperationInstrumentation.java | 65 +++++++ .../DistinctOperationInstrumentation.java | 64 +++++++ .../FindOperationInstrumentation.java | 64 +++++++ .../GroupOperationInstrumentation.java | 63 +++++++ ...stCollectionsOperationInstrumentation.java | 63 +++++++ .../ListIndexesOperationInstrumentation.java | 64 +++++++ ...InlineResultsOperationInstrumentation.java | 64 +++++++ ...ollectionScanOperationInstrumentation.java | 63 +++++++ .../UserExistsOperationInstrumentation.java | 63 +++++++ ...MapReduceReadOperationInstrumentation.java | 64 +++++++ ...MapReduceReadOperationInstrumentation.java | 64 +++++++ ...eToCollectionOperationInstrumentation.java | 64 +++++++ ...FindAndModifyOperationInstrumentation.java | 64 +++++++ .../BaseWriteOperationInstrumentation.java | 64 +++++++ .../CommandWriteOperationInstrumentation.java | 63 +++++++ ...ateCollectionOperationInstrumentation.java | 63 +++++++ ...CreateIndexesOperationInstrumentation.java | 64 +++++++ .../CreateViewOperationInstrumentation.java | 63 +++++++ ...ropCollectionOperationInstrumentation.java | 64 +++++++ .../DropDatabaseOperationInstrumentation.java | 64 +++++++ .../DropIndexOperationInstrumentation.java | 64 +++++++ ...eToCollectionOperationInstrumentation.java | 64 +++++++ ...ixedBulkWriteOperationInstrumentation.java | 64 +++++++ ...ameCollectionOperationInstrumentation.java | 64 +++++++ ...OperationDatabaseConstructInterceptor.java | 33 ++++ ...perationNamespaceConstructInterceptor.java | 34 ++++ ...ppedMapReduceReadOperationInterceptor.java | 32 ++++ .../v3/support/MongoNamespaceInfo.java | 62 +++++++ .../v3/support/MongoOperationHelper.java | 16 ++ .../mongodb/v3/support/MongoSpanHelper.java | 22 ++- .../src/main/resources/skywalking-plugin.def | 34 +++- .../v30/MongoDBInterceptorTest.java | 86 ++++++++-- ...ngoDBOperationExecutorInterceptorTest.java | 122 ++++++++++--- ...AggregateOperationImplInstrumentation.java | 4 +- .../AggregateOperationInstrumentation.java | 4 +- ...OperationDatabaseConstructInterceptor.java | 3 +- ...perationNamespaceConstructInterceptor.java | 4 +- ...ppedMapReduceReadOperationInterceptor.java | 5 +- .../v4/support/MongoNamespaceInfo.java | 62 +++++++ .../v4/support/MongoOperationHelper.java | 16 ++ .../mongodb/v4/support/MongoSpanHelper.java | 23 ++- ...ngoDBOperationExecutorInterceptorTest.java | 162 +++++++++++++++--- .../config/expectedData.yaml | 36 +++- .../mongodb/controller/CaseController.java | 14 ++ .../config/expectedData.yaml | 29 +++- .../mongodb/controller/CaseController.java | 14 ++ 52 files changed, 2578 insertions(+), 92 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateExplainOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateOperationImplInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ChangeStreamOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/CommandReadOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/CountOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/DistinctOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/FindOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/GroupOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ListCollectionsOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ListIndexesOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/MapReduceWithInlineResultsOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ParallelCollectionScanOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/UserExistsOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/WrappedMapReduceReadOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/v36/readOperation/WrappedMapReduceReadOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/AggregateToCollectionOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/BaseFindAndModifyOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/BaseWriteOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CommandWriteOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateCollectionOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateIndexesOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateViewOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropCollectionOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropDatabaseOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropIndexOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/MapReduceToCollectionOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/MixedBulkWriteOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/RenameCollectionOperationInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/OperationDatabaseConstructInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/OperationNamespaceConstructInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/WrappedMapReduceReadOperationInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoNamespaceInfo.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoNamespaceInfo.java diff --git a/CHANGES.md b/CHANGES.md index c2c322b280..c80b2ac858 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ Release Notes. * Fix intermittent ClassCircularityError by preloading ThreadLocalRandom since ByteBuddy 1.12.11 * Add witness class/method for resteasy-server plugin(v3/v4/v6) * Add async-profiler feature for performance analysis +* Support db.instance tag,db.collection tag and AggregateOperation span for mongodb plugin(3.x/4.x) All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateExplainOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateExplainOperationInstrumentation.java new file mode 100644 index 0000000000..929935a2c1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateExplainOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class AggregateExplainOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.AggregateExplainOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateOperationImplInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateOperationImplInstrumentation.java new file mode 100644 index 0000000000..208d0a2146 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateOperationImplInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class AggregateOperationImplInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.AggregateOperationImpl"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateOperationInstrumentation.java new file mode 100644 index 0000000000..bffd857fcb --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/AggregateOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class AggregateOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.AggregateOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ChangeStreamOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ChangeStreamOperationInstrumentation.java new file mode 100644 index 0000000000..f71ba7e4db --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ChangeStreamOperationInstrumentation.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class ChangeStreamOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.ChangeStreamOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(5); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/CommandReadOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/CommandReadOperationInstrumentation.java new file mode 100644 index 0000000000..ab317963f2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/CommandReadOperationInstrumentation.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class CommandReadOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.CommandReadOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationDatabaseConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/CountOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/CountOperationInstrumentation.java new file mode 100644 index 0000000000..6ee8e1ea29 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/CountOperationInstrumentation.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class CountOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.CountOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/DistinctOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/DistinctOperationInstrumentation.java new file mode 100644 index 0000000000..43cf1f9db3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/DistinctOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class DistinctOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.DistinctOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/FindOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/FindOperationInstrumentation.java new file mode 100644 index 0000000000..702d78138a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/FindOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class FindOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.FindOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/GroupOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/GroupOperationInstrumentation.java new file mode 100644 index 0000000000..0ad153cdef --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/GroupOperationInstrumentation.java @@ -0,0 +1,63 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class GroupOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.GroupOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ListCollectionsOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ListCollectionsOperationInstrumentation.java new file mode 100644 index 0000000000..0eff3237db --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ListCollectionsOperationInstrumentation.java @@ -0,0 +1,63 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class ListCollectionsOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.ListCollectionsOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationDatabaseConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ListIndexesOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ListIndexesOperationInstrumentation.java new file mode 100644 index 0000000000..7a1870badc --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ListIndexesOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class ListIndexesOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.ListIndexesOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/MapReduceWithInlineResultsOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/MapReduceWithInlineResultsOperationInstrumentation.java new file mode 100644 index 0000000000..e0fcadfecf --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/MapReduceWithInlineResultsOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class MapReduceWithInlineResultsOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.MapReduceWithInlineResultsOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ParallelCollectionScanOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ParallelCollectionScanOperationInstrumentation.java new file mode 100644 index 0000000000..554d178570 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/ParallelCollectionScanOperationInstrumentation.java @@ -0,0 +1,63 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class ParallelCollectionScanOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.ParallelCollectionScanOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/UserExistsOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/UserExistsOperationInstrumentation.java new file mode 100644 index 0000000000..393b0096a7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/UserExistsOperationInstrumentation.java @@ -0,0 +1,63 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class UserExistsOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.UserExistsOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationDatabaseConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/WrappedMapReduceReadOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/WrappedMapReduceReadOperationInstrumentation.java new file mode 100644 index 0000000000..4e76a8e06c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/readOperation/WrappedMapReduceReadOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class WrappedMapReduceReadOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.MapReduceIterableImpl"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/v36/readOperation/WrappedMapReduceReadOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/v36/readOperation/WrappedMapReduceReadOperationInstrumentation.java new file mode 100644 index 0000000000..c3fabf603e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/v36/readOperation/WrappedMapReduceReadOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.v36.readOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class WrappedMapReduceReadOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.client.internal.MapReduceIterableImpl$WrappedMapReduceReadOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.WrappedMapReduceReadOperationInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/AggregateToCollectionOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/AggregateToCollectionOperationInstrumentation.java new file mode 100644 index 0000000000..62bde0f7f8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/AggregateToCollectionOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class AggregateToCollectionOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.AggregateToCollectionOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(5); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/BaseFindAndModifyOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/BaseFindAndModifyOperationInstrumentation.java new file mode 100644 index 0000000000..bb1c0445ee --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/BaseFindAndModifyOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class BaseFindAndModifyOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.BaseFindAndModifyOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/BaseWriteOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/BaseWriteOperationInstrumentation.java new file mode 100644 index 0000000000..fdb6b8ffe3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/BaseWriteOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class BaseWriteOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.BaseWriteOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(4); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CommandWriteOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CommandWriteOperationInstrumentation.java new file mode 100644 index 0000000000..77d3d4f165 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CommandWriteOperationInstrumentation.java @@ -0,0 +1,63 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class CommandWriteOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.CommandWriteOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationDatabaseConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateCollectionOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateCollectionOperationInstrumentation.java new file mode 100644 index 0000000000..a5f45f68e3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateCollectionOperationInstrumentation.java @@ -0,0 +1,63 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class CreateCollectionOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.CreateCollectionOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationDatabaseConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(3); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateIndexesOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateIndexesOperationInstrumentation.java new file mode 100644 index 0000000000..556205173a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateIndexesOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class CreateIndexesOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.CreateIndexesOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(3); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateViewOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateViewOperationInstrumentation.java new file mode 100644 index 0000000000..e16c434818 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/CreateViewOperationInstrumentation.java @@ -0,0 +1,63 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class CreateViewOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.CreateViewOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationDatabaseConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropCollectionOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropCollectionOperationInstrumentation.java new file mode 100644 index 0000000000..88a04f6900 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropCollectionOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class DropCollectionOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.DropCollectionOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(2); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropDatabaseOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropDatabaseOperationInstrumentation.java new file mode 100644 index 0000000000..88450fec86 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropDatabaseOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class DropDatabaseOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.DropDatabaseOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationDatabaseConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(2); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropIndexOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropIndexOperationInstrumentation.java new file mode 100644 index 0000000000..8be077745b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/DropIndexOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class DropIndexOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.DropIndexOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(3); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/MapReduceToCollectionOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/MapReduceToCollectionOperationInstrumentation.java new file mode 100644 index 0000000000..cc72bd315b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/MapReduceToCollectionOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class MapReduceToCollectionOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.MapReduceToCollectionOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(5); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/MixedBulkWriteOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/MixedBulkWriteOperationInstrumentation.java new file mode 100644 index 0000000000..44a90e3001 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/MixedBulkWriteOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class MixedBulkWriteOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.MixedBulkWriteOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/RenameCollectionOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/RenameCollectionOperationInstrumentation.java new file mode 100644 index 0000000000..95c9a4fdb9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/define/writeOperation/RenameCollectionOperationInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.mongodb.v3.define.writeOperation; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class RenameCollectionOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.operation.RenameCollectionOperation"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.operation.OperationNamespaceConstructInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(3); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/OperationDatabaseConstructInterceptor.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/OperationDatabaseConstructInterceptor.java new file mode 100644 index 0000000000..a948de5128 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/OperationDatabaseConstructInterceptor.java @@ -0,0 +1,33 @@ +/* + * 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.mongodb.v3.interceptor.operation; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.mongodb.v3.support.MongoNamespaceInfo; + +public class OperationDatabaseConstructInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + String databaseName = (String) allArguments[0]; + objInst.setSkyWalkingDynamicField(new MongoNamespaceInfo(databaseName)); + } + +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/OperationNamespaceConstructInterceptor.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/OperationNamespaceConstructInterceptor.java new file mode 100644 index 0000000000..f6c97a6d37 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/OperationNamespaceConstructInterceptor.java @@ -0,0 +1,34 @@ +/* + * 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.mongodb.v3.interceptor.operation; + +import com.mongodb.MongoNamespace; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.mongodb.v3.support.MongoNamespaceInfo; + +public class OperationNamespaceConstructInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + MongoNamespace mongoNamespace = (MongoNamespace) allArguments[0]; + objInst.setSkyWalkingDynamicField(new MongoNamespaceInfo(mongoNamespace)); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/WrappedMapReduceReadOperationInterceptor.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/WrappedMapReduceReadOperationInterceptor.java new file mode 100644 index 0000000000..3cb37c8cb5 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/operation/WrappedMapReduceReadOperationInterceptor.java @@ -0,0 +1,32 @@ +/* + * 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.mongodb.v3.interceptor.operation; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +public class WrappedMapReduceReadOperationInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + EnhancedInstance enhancedInstance = (EnhancedInstance) allArguments[0]; + objInst.setSkyWalkingDynamicField(enhancedInstance.getSkyWalkingDynamicField()); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoNamespaceInfo.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoNamespaceInfo.java new file mode 100644 index 0000000000..16ba7f8aae --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoNamespaceInfo.java @@ -0,0 +1,62 @@ +/* + * 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.mongodb.v3.support; + +import com.mongodb.MongoNamespace; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import org.apache.skywalking.apm.util.StringUtil; + +@EqualsAndHashCode +@Getter +public class MongoNamespaceInfo { + + private final String databaseName; + private final String collectionName; + + public MongoNamespaceInfo(String databaseName) { + this(databaseName, null); + } + + public MongoNamespaceInfo(MongoNamespace mongoNamespace) { + this(mongoNamespace.getDatabaseName(), mongoNamespace.getCollectionName()); + } + + public MongoNamespaceInfo(String databaseName, String collectionName) { + this.databaseName = databaseName; + this.collectionName = collectionName; + } + + public String getDatabaseName() { + return databaseName; + } + + public String getCollectionName() { + return collectionName; + } + + public String toString() { + if (StringUtil.isNotBlank(collectionName)) { + return databaseName + '.' + collectionName; + } else { + return databaseName; + } + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoOperationHelper.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoOperationHelper.java index 99ab80c051..d68d642ec0 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoOperationHelper.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoOperationHelper.java @@ -22,6 +22,7 @@ import com.mongodb.bulk.InsertRequest; import com.mongodb.bulk.UpdateRequest; import com.mongodb.bulk.WriteRequest; +import com.mongodb.operation.AggregateOperation; import com.mongodb.operation.CountOperation; import com.mongodb.operation.CreateCollectionOperation; import com.mongodb.operation.CreateIndexesOperation; @@ -104,6 +105,9 @@ public static String getTraceParam(Object obj) { } else if (obj instanceof FindAndUpdateOperation) { BsonDocument filter = ((FindAndUpdateOperation) obj).getFilter(); return limitFilter(filter.toString()); + } else if (obj instanceof AggregateOperation) { + List pipelines = ((AggregateOperation) obj).getPipeline(); + return getPipelines(pipelines); } else if (obj instanceof MapReduceToCollectionOperation) { BsonDocument filter = ((MapReduceToCollectionOperation) obj).getFilter(); return limitFilter(filter.toString()); @@ -115,6 +119,18 @@ public static String getTraceParam(Object obj) { } } + private static String getPipelines(List pipelines) { + StringBuilder params = new StringBuilder(); + for (BsonDocument pipeline : pipelines) { + params.append(pipeline.toString()).append(","); + final int filterLengthLimit = MongoPluginConfig.Plugin.MongoDB.FILTER_LENGTH_LIMIT; + if (filterLengthLimit > 0 && params.length() > filterLengthLimit) { + return params.substring(0, filterLengthLimit) + "..."; + } + } + return params.toString(); + } + private static String getFilter(List writeRequestList) { StringBuilder params = new StringBuilder(); for (WriteRequest request : writeRequestList) { diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoSpanHelper.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoSpanHelper.java index 759abc4cd0..c7a88151a4 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoSpanHelper.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v3/support/MongoSpanHelper.java @@ -18,28 +18,48 @@ package org.apache.skywalking.apm.plugin.mongodb.v3.support; +import lombok.SneakyThrows; import org.apache.skywalking.apm.agent.core.context.ContextCarrier; import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.AbstractTag; import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.mongodb.v3.MongoPluginConfig; +import org.apache.skywalking.apm.util.StringUtil; public class MongoSpanHelper { + private static final AbstractTag DB_COLLECTION_TAG = Tags.ofKey("db.collection"); + private MongoSpanHelper() { } + @SneakyThrows public static void createExitSpan(String executeMethod, String remotePeer, Object operation) { AbstractSpan span = ContextManager.createExitSpan( - MongoConstants.MONGO_DB_OP_PREFIX + executeMethod, new ContextCarrier(), remotePeer); + MongoConstants.MONGO_DB_OP_PREFIX + executeMethod, new ContextCarrier(), remotePeer); span.setComponent(ComponentsDefine.MONGO_DRIVER); Tags.DB_TYPE.set(span, MongoConstants.DB_TYPE); SpanLayer.asDB(span); + if (operation instanceof EnhancedInstance) { + MongoNamespaceInfo mongoNamespaceInfo = (MongoNamespaceInfo) ((EnhancedInstance) operation).getSkyWalkingDynamicField(); + if (mongoNamespaceInfo != null) { + if (StringUtil.isNotEmpty(mongoNamespaceInfo.getDatabaseName())) { + Tags.DB_INSTANCE.set(span, mongoNamespaceInfo.getDatabaseName()); + } + if (StringUtil.isNotEmpty(mongoNamespaceInfo.getCollectionName())) { + span.tag(DB_COLLECTION_TAG, mongoNamespaceInfo.getCollectionName()); + } + } + } + if (MongoPluginConfig.Plugin.MongoDB.TRACE_PARAM) { Tags.DB_BIND_VARIABLES.set(span, MongoOperationHelper.getTraceParam(operation)); } } + } diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/resources/skywalking-plugin.def index 8416fd8e52..8e6b05fdf1 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/main/resources/skywalking-plugin.def @@ -19,8 +19,40 @@ mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.v30.MongoDBInstru # v3.7.x~ mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.v37.MongoDBClientDelegateInstrumentation mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.v37.MongoDBOperationExecutorInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.v36.readOperation.WrappedMapReduceReadOperationInstrumentation # v3.8.x~ mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.v38.MongoDBOperationExecutorInstrumentation # v3.6.x mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.v36.MongoDBInstrumentation -mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.v36.MongoDBOperationExecutorInstrumentation \ No newline at end of file +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.v36.MongoDBOperationExecutorInstrumentation + +# readOperation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.AggregateExplainOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.AggregateOperationImplInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.AggregateOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.ChangeStreamOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.CommandReadOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.CountOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.DistinctOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.FindOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.ListCollectionsOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.ListIndexesOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.MapReduceWithInlineResultsOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.WrappedMapReduceReadOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.GroupOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.ParallelCollectionScanOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.readOperation.UserExistsOperationInstrumentation +# writeOperation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.AggregateToCollectionOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.BaseFindAndModifyOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.BaseWriteOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.CommandWriteOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.CreateCollectionOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.CreateIndexesOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.CreateViewOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.DropCollectionOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.DropDatabaseOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.DropIndexOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.MapReduceToCollectionOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.MixedBulkWriteOperationInstrumentation +mongodb-3.x=org.apache.skywalking.apm.plugin.mongodb.v3.define.writeOperation.RenameCollectionOperationInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/v30/MongoDBInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/v30/MongoDBInterceptorTest.java index 62d28a6c14..2319ad54e3 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/v30/MongoDBInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/v30/MongoDBInterceptorTest.java @@ -18,12 +18,10 @@ package org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.v30; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import java.lang.reflect.Method; -import java.util.List; +import com.mongodb.Mongo; +import com.mongodb.MongoNamespace; +import com.mongodb.operation.AggregateOperation; +import com.mongodb.operation.FindOperation; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.LogDataEntity; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; @@ -38,6 +36,7 @@ import org.apache.skywalking.apm.agent.test.tools.SpanAssert; import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; import org.apache.skywalking.apm.plugin.mongodb.v3.MongoPluginConfig; +import org.apache.skywalking.apm.plugin.mongodb.v3.support.MongoNamespaceInfo; import org.bson.BsonDocument; import org.bson.BsonString; import org.bson.codecs.Decoder; @@ -48,11 +47,19 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import com.mongodb.Mongo; -import com.mongodb.MongoNamespace; -import com.mongodb.operation.FindOperation; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @RunWith(TracingSegmentRunner.class) public class MongoDBInterceptorTest { @@ -67,11 +74,16 @@ public class MongoDBInterceptorTest { private MongoDBInterceptor interceptor; + private FindOperation enhancedInstanceForFindOperation; + @Mock private EnhancedInstance enhancedInstance; private Object[] arguments; + private Class[] argumentTypes; + private Decoder decoder; + private MongoNamespace mongoNamespace; @SuppressWarnings({ "rawtypes", @@ -88,12 +100,14 @@ public void setUp() throws Exception { BsonDocument document = new BsonDocument(); document.append("name", new BsonString("by")); - MongoNamespace mongoNamespace = new MongoNamespace("test.user"); - Decoder decoder = mock(Decoder.class); + mongoNamespace = new MongoNamespace("test.user"); + decoder = mock(Decoder.class); FindOperation findOperation = new FindOperation(mongoNamespace, decoder); findOperation.filter(document); - - arguments = new Object[] {findOperation}; + enhancedInstanceForFindOperation = mock(FindOperation.class, Mockito.withSettings().extraInterfaces(EnhancedInstance.class)); + when(((EnhancedInstance) enhancedInstanceForFindOperation).getSkyWalkingDynamicField()).thenReturn(new MongoNamespaceInfo(mongoNamespace)); + when(enhancedInstanceForFindOperation.getFilter()).thenReturn(findOperation.getFilter()); + arguments = new Object[] {enhancedInstanceForFindOperation}; argumentTypes = new Class[] {findOperation.getClass()}; } @@ -105,7 +119,29 @@ public void testIntercept() throws Throwable { MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); List spans = SegmentHelper.getSpans(traceSegment); - assertRedisSpan(spans.get(0)); + assertFindOperationSpan(spans.get(0)); + } + + @Test + public void testAggregateOperationIntercept() throws Throwable { + MongoNamespace mongoNamespace = new MongoNamespace("test.user"); + BsonDocument matchStage = new BsonDocument("$match", new BsonDocument("name", new BsonString("by"))); + List pipeline = Collections.singletonList(matchStage); + AggregateOperation aggregateOperation = new AggregateOperation(mongoNamespace, pipeline, decoder); + + AggregateOperation enhancedInstanceForAggregateOperation = mock(AggregateOperation.class, Mockito.withSettings().extraInterfaces(EnhancedInstance.class)); + when(((EnhancedInstance) enhancedInstanceForAggregateOperation).getSkyWalkingDynamicField()).thenReturn(new MongoNamespaceInfo(mongoNamespace)); + when(enhancedInstanceForAggregateOperation.getPipeline()).thenReturn(aggregateOperation.getPipeline()); + Object[] arguments = {enhancedInstanceForAggregateOperation}; + Class[] argumentTypes = {aggregateOperation.getClass()}; + + interceptor.beforeMethod(enhancedInstance, getExecuteMethod(), arguments, argumentTypes, null); + interceptor.afterMethod(enhancedInstance, getExecuteMethod(), arguments, argumentTypes, null); + + MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertMongoAggregateOperationSpan(spans.get(0)); } @Test @@ -118,18 +154,32 @@ public void testInterceptWithException() throws Throwable { MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); List spans = SegmentHelper.getSpans(traceSegment); - assertRedisSpan(spans.get(0)); + assertFindOperationSpan(spans.get(0)); List logDataEntities = SpanHelper.getLogs(spans.get(0)); assertThat(logDataEntities.size(), is(1)); SpanAssert.assertException(logDataEntities.get(0), RuntimeException.class); } - private void assertRedisSpan(AbstractTracingSpan span) { - assertThat(span.getOperationName(), is("MongoDB/FindOperation")); + private void assertFindOperationSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), startsWith("MongoDB/FindOperation")); + assertThat(SpanHelper.getComponentId(span), is(42)); + List tags = SpanHelper.getTags(span); + assertThat(tags.get(0).getValue(), is("MongoDB")); + assertThat(tags.get(1).getValue(), is("test")); + assertThat(tags.get(2).getValue(), is("user")); + assertThat(tags.get(3).getValue(), is("{\"name\": \"by\"}")); + assertThat(span.isExit(), is(true)); + assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.DB)); + } + + private void assertMongoAggregateOperationSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), startsWith("MongoDB/AggregateOperation")); assertThat(SpanHelper.getComponentId(span), is(42)); List tags = SpanHelper.getTags(span); - assertThat(tags.get(1).getValue(), is("{\"name\": \"by\"}")); assertThat(tags.get(0).getValue(), is("MongoDB")); + assertThat(tags.get(1).getValue(), is("test")); + assertThat(tags.get(2).getValue(), is("user")); + assertThat(tags.get(3).getValue(), is("{\"$match\": {\"name\": \"by\"}},")); assertThat(span.isExit(), is(true)); assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.DB)); } diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/v37/MongoDBOperationExecutorInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/v37/MongoDBOperationExecutorInterceptorTest.java index 60de9f5c21..8c6112e7fc 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/v37/MongoDBOperationExecutorInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v3/interceptor/v37/MongoDBOperationExecutorInterceptorTest.java @@ -18,12 +18,13 @@ package org.apache.skywalking.apm.plugin.mongodb.v3.interceptor.v37; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import java.lang.reflect.Method; -import java.util.List; +import com.mongodb.MongoNamespace; +import com.mongodb.ReadConcern; +import com.mongodb.client.internal.OperationExecutor; +import com.mongodb.operation.AggregateOperation; +import com.mongodb.operation.CreateCollectionOperation; +import com.mongodb.operation.FindOperation; +import com.mongodb.operation.WriteOperation; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.LogDataEntity; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; @@ -38,6 +39,7 @@ import org.apache.skywalking.apm.agent.test.tools.SpanAssert; import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; import org.apache.skywalking.apm.plugin.mongodb.v3.MongoPluginConfig; +import org.apache.skywalking.apm.plugin.mongodb.v3.support.MongoNamespaceInfo; import org.bson.BsonDocument; import org.bson.BsonString; import org.bson.codecs.Decoder; @@ -48,13 +50,19 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import com.mongodb.MongoNamespace; -import com.mongodb.ReadConcern; -import com.mongodb.client.internal.OperationExecutor; -import com.mongodb.operation.FindOperation; -import com.mongodb.operation.WriteOperation; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @RunWith(TracingSegmentRunner.class) public class MongoDBOperationExecutorInterceptorTest { @@ -70,11 +78,15 @@ public class MongoDBOperationExecutorInterceptorTest { @Mock private EnhancedInstance enhancedInstance; + private FindOperation enhancedInstanceForFindOperation; + private MongoDBOperationExecutorInterceptor interceptor; private Object[] arguments; private Class[] argumentTypes; + private Decoder decoder; + private MongoNamespace mongoNamespace; @Before public void setUp() { @@ -87,12 +99,14 @@ public void setUp() { BsonDocument document = new BsonDocument(); document.append("name", new BsonString("by")); - MongoNamespace mongoNamespace = new MongoNamespace("test.user"); - Decoder decoder = mock(Decoder.class); + mongoNamespace = new MongoNamespace("test.user"); + decoder = mock(Decoder.class); FindOperation findOperation = new FindOperation(mongoNamespace, decoder); findOperation.filter(document); - - arguments = new Object[] {findOperation}; + enhancedInstanceForFindOperation = mock(FindOperation.class, Mockito.withSettings().extraInterfaces(EnhancedInstance.class)); + when(((EnhancedInstance) enhancedInstanceForFindOperation).getSkyWalkingDynamicField()).thenReturn(new MongoNamespaceInfo(mongoNamespace)); + when(enhancedInstanceForFindOperation.getFilter()).thenReturn(findOperation.getFilter()); + arguments = new Object[] {enhancedInstanceForFindOperation}; argumentTypes = new Class[] {findOperation.getClass()}; } @@ -104,11 +118,51 @@ public void testIntercept() throws Throwable { MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); List spans = SegmentHelper.getSpans(traceSegment); - assertRedisSpan(spans.get(0)); + assertMongoFindOperationSpan(spans.get(0)); } @Test - public void testInterceptWithException() throws Throwable { + public void testCreateCollectionOperationIntercept() throws Throwable { + CreateCollectionOperation createCollectionOperation = new CreateCollectionOperation("test", "user"); + CreateCollectionOperation enhancedInstanceForCreateCollectionOperation = mock(CreateCollectionOperation.class, Mockito.withSettings().extraInterfaces(EnhancedInstance.class)); + when(((EnhancedInstance) enhancedInstanceForCreateCollectionOperation).getSkyWalkingDynamicField()).thenReturn(new MongoNamespaceInfo(mongoNamespace)); + when(enhancedInstanceForCreateCollectionOperation.getCollectionName()).thenReturn("user"); + Object[] arguments = {enhancedInstanceForCreateCollectionOperation}; + Class[] argumentTypes = {createCollectionOperation.getClass()}; + + interceptor.beforeMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); + interceptor.afterMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); + + MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertMongoCreateCollectionOperationSpan(spans.get(0)); + } + + @Test + public void testAggregateOperationIntercept() throws Throwable { + MongoNamespace mongoNamespace = new MongoNamespace("test.user"); + BsonDocument matchStage = new BsonDocument("$match", new BsonDocument("name", new BsonString("by"))); + List pipeline = Collections.singletonList(matchStage); + AggregateOperation aggregateOperation = new AggregateOperation(mongoNamespace, pipeline, decoder); + + AggregateOperation enhancedInstanceForAggregateOperation = mock(AggregateOperation.class, Mockito.withSettings().extraInterfaces(EnhancedInstance.class)); + when(((EnhancedInstance) enhancedInstanceForAggregateOperation).getSkyWalkingDynamicField()).thenReturn(new MongoNamespaceInfo(mongoNamespace)); + when(enhancedInstanceForAggregateOperation.getPipeline()).thenReturn(aggregateOperation.getPipeline()); + Object[] arguments = {enhancedInstanceForAggregateOperation}; + Class[] argumentTypes = {aggregateOperation.getClass()}; + + interceptor.beforeMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); + interceptor.afterMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); + + MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertMongoAggregateOperationSpan(spans.get(0)); + } + + @Test + public void testInterceptFindOperationWithException() throws Throwable { interceptor.beforeMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); interceptor.handleMethodException( enhancedInstance, getMethod(), arguments, argumentTypes, new RuntimeException()); @@ -117,18 +171,44 @@ public void testInterceptWithException() throws Throwable { MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); List spans = SegmentHelper.getSpans(traceSegment); - assertRedisSpan(spans.get(0)); + assertMongoFindOperationSpan(spans.get(0)); List logDataEntities = SpanHelper.getLogs(spans.get(0)); assertThat(logDataEntities.size(), is(1)); SpanAssert.assertException(logDataEntities.get(0), RuntimeException.class); } - private void assertRedisSpan(AbstractTracingSpan span) { - assertThat(span.getOperationName(), is("MongoDB/FindOperation")); + private void assertMongoCreateCollectionOperationSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), startsWith("MongoDB/CreateCollectionOperation")); + assertThat(SpanHelper.getComponentId(span), is(42)); + List tags = SpanHelper.getTags(span); + assertThat(tags.get(0).getValue(), is("MongoDB")); + assertThat(tags.get(1).getValue(), is("test")); + assertThat(tags.get(2).getValue(), is("user")); + assertThat(tags.get(3).getValue(), is("user")); + assertThat(span.isExit(), is(true)); + assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.DB)); + } + + private void assertMongoAggregateOperationSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), startsWith("MongoDB/AggregateOperation")); + assertThat(SpanHelper.getComponentId(span), is(42)); + List tags = SpanHelper.getTags(span); + assertThat(tags.get(0).getValue(), is("MongoDB")); + assertThat(tags.get(1).getValue(), is("test")); + assertThat(tags.get(2).getValue(), is("user")); + assertThat(tags.get(3).getValue(), is("{\"$match\": {\"name\": \"by\"}},")); + assertThat(span.isExit(), is(true)); + assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.DB)); + } + + private void assertMongoFindOperationSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), startsWith("MongoDB/FindOperation")); assertThat(SpanHelper.getComponentId(span), is(42)); List tags = SpanHelper.getTags(span); - assertThat(tags.get(1).getValue(), is("{\"name\": \"by\"}")); assertThat(tags.get(0).getValue(), is("MongoDB")); + assertThat(tags.get(1).getValue(), is("test")); + assertThat(tags.get(2).getValue(), is("user")); + assertThat(tags.get(3).getValue(), is("{\"name\": \"by\"}")); assertThat(span.isExit(), is(true)); assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.DB)); } diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/define/readOperation/AggregateOperationImplInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/define/readOperation/AggregateOperationImplInstrumentation.java index 49cb53e085..1e50102399 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/define/readOperation/AggregateOperationImplInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/define/readOperation/AggregateOperationImplInstrumentation.java @@ -26,7 +26,7 @@ import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static net.bytebuddy.matcher.ElementMatchers.any; public class AggregateOperationImplInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { @@ -53,7 +53,7 @@ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { @Override public ElementMatcher getConstructorMatcher() { - return takesArguments(4); + return any(); } @Override diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/define/readOperation/AggregateOperationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/define/readOperation/AggregateOperationInstrumentation.java index b95124195b..6e56abd504 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/define/readOperation/AggregateOperationInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/define/readOperation/AggregateOperationInstrumentation.java @@ -26,7 +26,7 @@ import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; -import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static net.bytebuddy.matcher.ElementMatchers.any; public class AggregateOperationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { @@ -53,7 +53,7 @@ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { @Override public ElementMatcher getConstructorMatcher() { - return takesArguments(5); + return any(); } @Override diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/OperationDatabaseConstructInterceptor.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/OperationDatabaseConstructInterceptor.java index a643e3f201..850b625153 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/OperationDatabaseConstructInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/OperationDatabaseConstructInterceptor.java @@ -20,13 +20,14 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.mongodb.v4.support.MongoNamespaceInfo; public class OperationDatabaseConstructInterceptor implements InstanceConstructorInterceptor { @Override public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { String databaseName = (String) allArguments[0]; - objInst.setSkyWalkingDynamicField(databaseName); + objInst.setSkyWalkingDynamicField(new MongoNamespaceInfo(databaseName)); } } \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/OperationNamespaceConstructInterceptor.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/OperationNamespaceConstructInterceptor.java index 6641012fbf..9a9fec49f0 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/OperationNamespaceConstructInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/OperationNamespaceConstructInterceptor.java @@ -21,14 +21,14 @@ import com.mongodb.MongoNamespace; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.mongodb.v4.support.MongoNamespaceInfo; public class OperationNamespaceConstructInterceptor implements InstanceConstructorInterceptor { @Override public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { MongoNamespace mongoNamespace = (MongoNamespace) allArguments[0]; - String databaseName = mongoNamespace.getDatabaseName(); - objInst.setSkyWalkingDynamicField(databaseName); + objInst.setSkyWalkingDynamicField(new MongoNamespaceInfo(mongoNamespace)); } } diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/WrappedMapReduceReadOperationInterceptor.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/WrappedMapReduceReadOperationInterceptor.java index 39c4699ffb..90614d3fc7 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/WrappedMapReduceReadOperationInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/interceptor/operation/WrappedMapReduceReadOperationInterceptor.java @@ -25,11 +25,8 @@ public class WrappedMapReduceReadOperationInterceptor implements InstanceConstru @Override public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { - if (allArguments[0] instanceof EnhancedInstance) { EnhancedInstance enhancedInstance = (EnhancedInstance) allArguments[0]; - String databaseName = (String) enhancedInstance.getSkyWalkingDynamicField(); - objInst.setSkyWalkingDynamicField(databaseName); - } + objInst.setSkyWalkingDynamicField(enhancedInstance.getSkyWalkingDynamicField()); } } diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoNamespaceInfo.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoNamespaceInfo.java new file mode 100644 index 0000000000..54d54b4d8a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoNamespaceInfo.java @@ -0,0 +1,62 @@ +/* + * 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.mongodb.v4.support; + +import com.mongodb.MongoNamespace; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import org.apache.skywalking.apm.util.StringUtil; + +@EqualsAndHashCode +@Getter +public class MongoNamespaceInfo { + + private final String databaseName; + private final String collectionName; + + public MongoNamespaceInfo(String databaseName) { + this(databaseName, null); + } + + public MongoNamespaceInfo(MongoNamespace mongoNamespace) { + this(mongoNamespace.getDatabaseName(), mongoNamespace.getCollectionName()); + } + + public MongoNamespaceInfo(String databaseName, String collectionName) { + this.databaseName = databaseName; + this.collectionName = collectionName; + } + + public String getDatabaseName() { + return databaseName; + } + + public String getCollectionName() { + return collectionName; + } + + public String toString() { + if (StringUtil.isNotBlank(collectionName)) { + return databaseName + '.' + collectionName; + } else { + return databaseName; + } + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoOperationHelper.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoOperationHelper.java index 45d0481fbc..8a561cc887 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoOperationHelper.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoOperationHelper.java @@ -22,6 +22,7 @@ import com.mongodb.internal.bulk.InsertRequest; import com.mongodb.internal.bulk.UpdateRequest; import com.mongodb.internal.bulk.WriteRequest; +import com.mongodb.internal.operation.AggregateOperation; import com.mongodb.internal.operation.CountOperation; import com.mongodb.internal.operation.CreateCollectionOperation; import com.mongodb.internal.operation.CreateIndexesOperation; @@ -101,6 +102,9 @@ public static String getTraceParam(Object obj) { } else if (obj instanceof FindAndUpdateOperation) { BsonDocument filter = ((FindAndUpdateOperation) obj).getFilter(); return limitFilter(filter.toString()); + } else if (obj instanceof AggregateOperation) { + List pipelines = ((AggregateOperation) obj).getPipeline(); + return getPipelines(pipelines); } else if (obj instanceof MapReduceToCollectionOperation) { BsonDocument filter = ((MapReduceToCollectionOperation) obj).getFilter(); return limitFilter(filter.toString()); @@ -112,6 +116,18 @@ public static String getTraceParam(Object obj) { } } + private static String getPipelines(List pipelines) { + StringBuilder params = new StringBuilder(); + for (BsonDocument pipeline : pipelines) { + params.append(pipeline.toString()).append(","); + final int filterLengthLimit = MongoPluginConfig.Plugin.MongoDB.FILTER_LENGTH_LIMIT; + if (filterLengthLimit > 0 && params.length() > filterLengthLimit) { + return params.substring(0, filterLengthLimit) + "..."; + } + } + return params.toString(); + } + private static String getFilter(List writeRequestList) { StringBuilder params = new StringBuilder(); for (WriteRequest request : writeRequestList) { diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoSpanHelper.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoSpanHelper.java index 4f81a0f058..d87b66a825 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoSpanHelper.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoSpanHelper.java @@ -20,34 +20,44 @@ import org.apache.skywalking.apm.agent.core.context.ContextCarrier; import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.AbstractTag; import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.util.StringUtil; public class MongoSpanHelper { + private static final AbstractTag DB_COLLECTION_TAG = Tags.ofKey("db.collection"); + private MongoSpanHelper() { } /** * createExitSpan + * * @param executeMethod executeMethod - * @param remotePeer remotePeer - * @param operation operation + * @param remotePeer remotePeer + * @param operation operation */ public static void createExitSpan(String executeMethod, String remotePeer, Object operation) { AbstractSpan span = ContextManager.createExitSpan( - MongoConstants.MONGO_DB_OP_PREFIX + executeMethod, new ContextCarrier(), remotePeer); + MongoConstants.MONGO_DB_OP_PREFIX + executeMethod, new ContextCarrier(), remotePeer); span.setComponent(ComponentsDefine.MONGO_DRIVER); Tags.DB_TYPE.set(span, MongoConstants.DB_TYPE); SpanLayer.asDB(span); if (operation instanceof EnhancedInstance) { - Object databaseName = ((EnhancedInstance) operation).getSkyWalkingDynamicField(); - if (databaseName != null) { - Tags.DB_INSTANCE.set(span, (String) databaseName); + MongoNamespaceInfo mongoNamespaceInfo = (MongoNamespaceInfo) ((EnhancedInstance) operation).getSkyWalkingDynamicField(); + if (mongoNamespaceInfo != null) { + if (StringUtil.isNotEmpty(mongoNamespaceInfo.getDatabaseName())) { + Tags.DB_INSTANCE.set(span, mongoNamespaceInfo.getDatabaseName()); + } + if (StringUtil.isNotEmpty(mongoNamespaceInfo.getCollectionName())) { + span.tag(DB_COLLECTION_TAG, mongoNamespaceInfo.getCollectionName()); + } } } @@ -56,3 +66,4 @@ public static void createExitSpan(String executeMethod, String remotePeer, Objec } } } + diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v4/MongoDBOperationExecutorInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v4/MongoDBOperationExecutorInterceptorTest.java index ed2154056e..4bb4b1213b 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v4/MongoDBOperationExecutorInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/mongodb/v4/MongoDBOperationExecutorInterceptorTest.java @@ -18,12 +18,13 @@ package org.apache.skywalking.apm.plugin.mongodb.v4; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import java.lang.reflect.Method; -import java.util.List; +import com.mongodb.MongoNamespace; +import com.mongodb.ReadConcern; +import com.mongodb.client.internal.OperationExecutor; +import com.mongodb.internal.operation.AggregateOperation; +import com.mongodb.internal.operation.CreateCollectionOperation; +import com.mongodb.internal.operation.FindOperation; +import com.mongodb.internal.operation.WriteOperation; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.LogDataEntity; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; @@ -38,24 +39,34 @@ import org.apache.skywalking.apm.agent.test.tools.SpanAssert; import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; import org.apache.skywalking.apm.plugin.mongodb.v4.interceptor.MongoDBOperationExecutorInterceptor; +import org.apache.skywalking.apm.plugin.mongodb.v4.support.MongoNamespaceInfo; +import org.apache.skywalking.apm.plugin.mongodb.v4.interceptor.operation.OperationNamespaceConstructInterceptor; import org.apache.skywalking.apm.plugin.mongodb.v4.support.MongoPluginConfig; import org.bson.BsonDocument; import org.bson.BsonString; import org.bson.codecs.Decoder; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; +import org.hamcrest.core.Is; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import com.mongodb.MongoNamespace; -import com.mongodb.ReadConcern; -import com.mongodb.client.internal.OperationExecutor; -import com.mongodb.internal.operation.FindOperation; -import com.mongodb.internal.operation.WriteOperation; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; @RunWith(TracingSegmentRunner.class) public class MongoDBOperationExecutorInterceptorTest { @@ -71,32 +82,85 @@ public class MongoDBOperationExecutorInterceptorTest { @Mock private EnhancedInstance enhancedInstance; + private FindOperation enhancedInstanceForFindOperation; + + @Spy + private EnhancedInstance enhancedObjInstance = new EnhancedInstance() { + private MongoNamespaceInfo namespace; + + @Override + public Object getSkyWalkingDynamicField() { + return namespace; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.namespace = (MongoNamespaceInfo) value; + } + }; + private MongoDBOperationExecutorInterceptor interceptor; + private OperationNamespaceConstructInterceptor constructInterceptor; + private Object[] arguments; private Class[] argumentTypes; + private Decoder decoder; + + private MongoNamespace mongoNamespace; + + private MongoNamespaceInfo mongoNamespaceInfo; + @Before public void setUp() { interceptor = new MongoDBOperationExecutorInterceptor(); - + constructInterceptor = new OperationNamespaceConstructInterceptor(); + enhancedInstanceForFindOperation = mock(FindOperation.class, Mockito.withSettings().extraInterfaces(EnhancedInstance.class)); MongoPluginConfig.Plugin.MongoDB.TRACE_PARAM = true; - - when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn("127.0.0.1:27017"); - + decoder = mock(Decoder.class); + mongoNamespace = new MongoNamespace("test.user"); + mongoNamespaceInfo = new MongoNamespaceInfo(mongoNamespace); BsonDocument document = new BsonDocument(); document.append("name", new BsonString("by")); - MongoNamespace mongoNamespace = new MongoNamespace("test.user"); - Decoder decoder = mock(Decoder.class); + FindOperation findOperation = new FindOperation(mongoNamespace, decoder); findOperation.filter(document); - - arguments = new Object[] {findOperation}; + decoder = mock(Decoder.class); + when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn("127.0.0.1:27017"); + enhancedInstanceForFindOperation = mock(FindOperation.class, Mockito.withSettings().extraInterfaces(EnhancedInstance.class)); + when(((EnhancedInstance) enhancedInstanceForFindOperation).getSkyWalkingDynamicField()).thenReturn(mongoNamespaceInfo); + when(enhancedInstanceForFindOperation.getFilter()).thenReturn(findOperation.getFilter()); + arguments = new Object[] {enhancedInstanceForFindOperation}; argumentTypes = new Class[] {findOperation.getClass()}; } + @Test + public void testConstructIntercept() throws Throwable { + constructInterceptor.onConstruct(enhancedObjInstance, new Object[]{mongoNamespace}); + MatcherAssert.assertThat(enhancedObjInstance.getSkyWalkingDynamicField(), Is.is(new MongoNamespaceInfo(mongoNamespace))); + } + + @Test + public void testCreateCollectionOperationIntercept() throws Throwable { + CreateCollectionOperation createCollectionOperation = new CreateCollectionOperation("test", "user"); + CreateCollectionOperation enhancedInstanceForCreateCollectionOperation = mock(CreateCollectionOperation.class, Mockito.withSettings().extraInterfaces(EnhancedInstance.class)); + when(((EnhancedInstance) enhancedInstanceForCreateCollectionOperation).getSkyWalkingDynamicField()).thenReturn(new MongoNamespaceInfo("test")); + when(enhancedInstanceForCreateCollectionOperation.getCollectionName()).thenReturn("user"); + + Object[] arguments = {enhancedInstanceForCreateCollectionOperation}; + Class[] argumentTypes = {createCollectionOperation.getClass()}; + interceptor.beforeMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); + interceptor.afterMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); + + MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertMongoCreateCollectionOperationSpan(spans.get(0)); + } + @Test public void testIntercept() throws Throwable { interceptor.beforeMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); @@ -105,31 +169,77 @@ public void testIntercept() throws Throwable { MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); List spans = SegmentHelper.getSpans(traceSegment); - assertMongoSpan(spans.get(0)); + assertMongoFindOperationSpan(spans.get(0)); + } + + @Test + public void testAggregateOperationIntercept() throws Throwable { + MongoNamespace mongoNamespace = new MongoNamespace("test.user"); + BsonDocument matchStage = new BsonDocument("$match", new BsonDocument("name", new BsonString("by"))); + List pipeline = Collections.singletonList(matchStage); + AggregateOperation aggregateOperation = new AggregateOperation(mongoNamespace, pipeline, decoder); + + AggregateOperation enhancedInstanceForAggregateOperation = mock(AggregateOperation.class, Mockito.withSettings().extraInterfaces(EnhancedInstance.class)); + when(((EnhancedInstance) enhancedInstanceForAggregateOperation).getSkyWalkingDynamicField()).thenReturn(new MongoNamespaceInfo(mongoNamespace)); + when(enhancedInstanceForAggregateOperation.getPipeline()).thenReturn(aggregateOperation.getPipeline()); + Object[] arguments = {enhancedInstanceForAggregateOperation}; + Class[] argumentTypes = {aggregateOperation.getClass()}; + + interceptor.beforeMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); + interceptor.afterMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); + + MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertMongoAggregateOperationSpan(spans.get(0)); } @Test public void testInterceptWithException() throws Throwable { interceptor.beforeMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); - interceptor.handleMethodException( - enhancedInstance, getMethod(), arguments, argumentTypes, new RuntimeException()); + interceptor.handleMethodException(enhancedInstance, getMethod(), arguments, argumentTypes, new RuntimeException()); interceptor.afterMethod(enhancedInstance, getMethod(), arguments, argumentTypes, null); MatcherAssert.assertThat(segmentStorage.getTraceSegments().size(), is(1)); TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); List spans = SegmentHelper.getSpans(traceSegment); - assertMongoSpan(spans.get(0)); + assertMongoFindOperationSpan(spans.get(0)); List logDataEntities = SpanHelper.getLogs(spans.get(0)); assertThat(logDataEntities.size(), is(1)); SpanAssert.assertException(logDataEntities.get(0), RuntimeException.class); } - private void assertMongoSpan(AbstractTracingSpan span) { - assertThat(span.getOperationName(), is("MongoDB/FindOperation")); + private void assertMongoFindOperationSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), startsWith("MongoDB/FindOperation")); + assertThat(SpanHelper.getComponentId(span), is(42)); + List tags = SpanHelper.getTags(span); + assertThat(tags.get(0).getValue(), is("MongoDB")); + assertThat(tags.get(1).getValue(), is("test")); + assertThat(tags.get(2).getValue(), is("user")); + assertThat(tags.get(3).getValue(), is("{\"name\": \"by\"}")); + assertThat(span.isExit(), is(true)); + assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.DB)); + } + + private void assertMongoCreateCollectionOperationSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), startsWith("MongoDB/CreateCollectionOperation")); + assertThat(SpanHelper.getComponentId(span), is(42)); + List tags = SpanHelper.getTags(span); + assertThat(tags.get(0).getValue(), is("MongoDB")); + assertThat(tags.get(1).getValue(), is("test")); + assertThat(tags.get(2).getValue(), is("user")); + assertThat(span.isExit(), is(true)); + assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.DB)); + } + + private void assertMongoAggregateOperationSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), startsWith("MongoDB/AggregateOperation")); assertThat(SpanHelper.getComponentId(span), is(42)); List tags = SpanHelper.getTags(span); - assertThat(tags.get(1).getValue(), is("{\"name\": \"by\"}")); assertThat(tags.get(0).getValue(), is("MongoDB")); + assertThat(tags.get(1).getValue(), is("test")); + assertThat(tags.get(2).getValue(), is("user")); + assertThat(tags.get(3).getValue(), is("{\"$match\": {\"name\": \"by\"}},")); assertThat(span.isExit(), is(true)); assertThat(SpanHelper.getLayer(span), CoreMatchers.is(SpanLayer.DB)); } diff --git a/test/plugin/scenarios/mongodb-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/mongodb-3.x-scenario/config/expectedData.yaml index e17d7162cf..a050100ce9 100644 --- a/test/plugin/scenarios/mongodb-3.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/mongodb-3.x-scenario/config/expectedData.yaml @@ -31,6 +31,7 @@ segmentItems: peer: mongodb-server:27017 tags: - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} - {key: db.bind_vars, value: not null} skipAnalysis: 'false' - operationName: MongoDB/MixedBulkWriteOperation @@ -45,6 +46,8 @@ segmentItems: peer: mongodb-server:27017 tags: - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: not null} skipAnalysis: 'false' - operationName: MongoDB/FindOperation @@ -59,9 +62,11 @@ segmentItems: peer: mongodb-server:27017 tags: - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: not null} skipAnalysis: 'false' - - operationName: MongoDB/MixedBulkWriteOperation + - operationName: MongoDB/AggregateOperation parentSpanId: 0 spanId: 4 spanLayer: Database @@ -73,9 +78,11 @@ segmentItems: peer: mongodb-server:27017 tags: - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: not null} skipAnalysis: 'false' - - operationName: MongoDB/FindOperation + - operationName: MongoDB/MixedBulkWriteOperation parentSpanId: 0 spanId: 5 spanLayer: Database @@ -87,9 +94,11 @@ segmentItems: peer: mongodb-server:27017 tags: - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: not null} skipAnalysis: 'false' - - operationName: MongoDB/MixedBulkWriteOperation + - operationName: MongoDB/FindOperation parentSpanId: 0 spanId: 6 spanLayer: Database @@ -101,9 +110,11 @@ segmentItems: peer: mongodb-server:27017 tags: - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: not null} skipAnalysis: 'false' - - operationName: MongoDB/DropDatabaseOperation + - operationName: MongoDB/MixedBulkWriteOperation parentSpanId: 0 spanId: 7 spanLayer: Database @@ -115,6 +126,23 @@ segmentItems: peer: mongodb-server:27017 tags: - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} + - {key: db.bind_vars, value: not null} + skipAnalysis: 'false' + - operationName: MongoDB/DropDatabaseOperation + parentSpanId: 0 + spanId: 8 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} - {key: db.bind_vars, value: not null} skipAnalysis: 'false' - operationName: GET:/mongodb-case/case/mongodb diff --git a/test/plugin/scenarios/mongodb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java b/test/plugin/scenarios/mongodb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java index dad835c02a..d26f7d092e 100644 --- a/test/plugin/scenarios/mongodb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java +++ b/test/plugin/scenarios/mongodb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java @@ -19,16 +19,23 @@ package org.apache.skywalking.apm.testcase.mongodb.controller; import com.mongodb.MongoClient; +import com.mongodb.client.AggregateIterable; import com.mongodb.client.FindIterable; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Aggregates; +import com.mongodb.client.model.Filters; import org.bson.BsonDocument; import org.bson.Document; +import org.bson.conversions.Bson; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Arrays; +import java.util.List; + import static com.mongodb.client.model.Filters.eq; @RestController @@ -65,6 +72,13 @@ public String mongoDBCase() { FindIterable findIterable = collection.find(eq("name", "org")); findIterable.first(); + // AggregateOperation + List pipeline = Arrays.asList( + Aggregates.match(Filters.eq("name", "test")) + ); + AggregateIterable aggregateIterable = collection.aggregate(pipeline); + aggregateIterable.first(); + // MixedBulkWriteOperation collection.updateOne(eq("name", "org"), BsonDocument.parse("{ $set : { \"name\": \"testA\"} }")); diff --git a/test/plugin/scenarios/mongodb-4.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/mongodb-4.x-scenario/config/expectedData.yaml index 299d8b45ea..7673d38268 100644 --- a/test/plugin/scenarios/mongodb-4.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/mongodb-4.x-scenario/config/expectedData.yaml @@ -47,6 +47,7 @@ segmentItems: tags: - {key: db.type, value: MongoDB} - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: not null} skipAnalysis: 'false' - operationName: MongoDB/FindOperation @@ -62,9 +63,10 @@ segmentItems: tags: - {key: db.type, value: MongoDB} - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: '{"name": "org"}'} skipAnalysis: 'false' - - operationName: MongoDB/MixedBulkWriteOperation + - operationName: MongoDB/AggregateOperation parentSpanId: 0 spanId: 4 spanLayer: Database @@ -77,11 +79,28 @@ segmentItems: tags: - {key: db.type, value: MongoDB} - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} + - {key: db.bind_vars, value: '{"$match": {"name": "test"}},'} + skipAnalysis: 'false' + - operationName: MongoDB/MixedBulkWriteOperation + parentSpanId: 0 + spanId: 5 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: '{"name": "org"},'} skipAnalysis: 'false' - operationName: MongoDB/FindOperation parentSpanId: 0 - spanId: 5 + spanId: 6 spanLayer: Database startTime: nq 0 endTime: nq 0 @@ -92,11 +111,12 @@ segmentItems: tags: - {key: db.type, value: MongoDB} - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: '{"name": "testA"}'} skipAnalysis: 'false' - operationName: MongoDB/MixedBulkWriteOperation parentSpanId: 0 - spanId: 6 + spanId: 7 spanLayer: Database startTime: nq 0 endTime: nq 0 @@ -107,11 +127,12 @@ segmentItems: tags: - {key: db.type, value: MongoDB} - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} - {key: db.bind_vars, value: '{"id": "1"},'} skipAnalysis: 'false' - operationName: MongoDB/DropDatabaseOperation parentSpanId: 0 - spanId: 7 + spanId: 8 spanLayer: Database startTime: nq 0 endTime: nq 0 diff --git a/test/plugin/scenarios/mongodb-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java b/test/plugin/scenarios/mongodb-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java index 33dfea5768..e50909855c 100644 --- a/test/plugin/scenarios/mongodb-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java +++ b/test/plugin/scenarios/mongodb-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java @@ -18,18 +18,25 @@ package org.apache.skywalking.apm.testcase.mongodb.controller; +import com.mongodb.client.AggregateIterable; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.FindIterable; +import com.mongodb.client.model.Aggregates; +import com.mongodb.client.model.Filters; import org.bson.BsonDocument; import org.bson.Document; +import org.bson.conversions.Bson; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Arrays; +import java.util.List; + import static com.mongodb.client.model.Filters.eq; @RestController @@ -63,6 +70,13 @@ public String mongoDBCase() { FindIterable findIterable = collection.find(eq("name", "org")); findIterable.first(); + // AggregateOperation + List pipeline = Arrays.asList( + Aggregates.match(Filters.eq("name", "test")) + ); + AggregateIterable aggregateIterable = collection.aggregate(pipeline); + aggregateIterable.first(); + // MixedBulkWriteOperation collection.updateOne(eq("name", "org"), BsonDocument.parse("{ $set : { \"name\": \"testA\"} }")); From 2059fd4cb7f14f9c704cd82ddb81026b4315cf42 Mon Sep 17 00:00:00 2001 From: jiangyuan Date: Thu, 28 Nov 2024 17:05:32 +0800 Subject: [PATCH 039/114] Improve CustomizeConfiguration by avoiding repeatedly resolve file config (#730) --- CHANGES.md | 1 + .../conf/CustomizeConfiguration.java | 28 +++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c80b2ac858..8275c7e0fa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Release Notes. * Add witness class/method for resteasy-server plugin(v3/v4/v6) * Add async-profiler feature for performance analysis * Support db.instance tag,db.collection tag and AggregateOperation span for mongodb plugin(3.x/4.x) +* Improve CustomizeConfiguration by avoiding repeatedly resolve file config All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/CustomizeConfiguration.java b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/CustomizeConfiguration.java index ba48a9280e..ba3dd5f843 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/CustomizeConfiguration.java +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/src/main/java/org/apache/skywalking/apm/plugin/customize/conf/CustomizeConfiguration.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.ReentrantLock; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -67,6 +68,8 @@ public enum CustomizeConfiguration { private static final Map CONTEXT_ENHANCE_CLASSES = new HashMap<>(); private static final AtomicBoolean LOAD_FOR_CONFIGURATION = new AtomicBoolean(false); + private static volatile List> RESOLVED_FILE_CONFIGURATIONS; + private static final ReentrantLock RESOLVED_FILE_LOCK = new ReentrantLock(); /** * The loadForEnhance method is resolver configuration file, and parse it */ @@ -107,13 +110,26 @@ public synchronized void loadForConfiguration() { * @throws SAXException link {@link SAXException} */ private List> resolver() throws ParserConfigurationException, IOException, SAXException { - List> customizeMethods = new ArrayList>(); - File file = new File(CustomizePluginConfig.Plugin.Customize.ENHANCE_FILE); - if (file.exists() && file.isFile()) { - NodeList classNodeList = resolverFileClassDesc(file); - resolverClassNodeList(classNodeList, customizeMethods); + if (RESOLVED_FILE_CONFIGURATIONS != null) { + return RESOLVED_FILE_CONFIGURATIONS; } - return customizeMethods; + + RESOLVED_FILE_LOCK.lock(); + try { + if (RESOLVED_FILE_CONFIGURATIONS != null) { + return RESOLVED_FILE_CONFIGURATIONS; + } + List> customizeMethods = new ArrayList>(); + File file = new File(CustomizePluginConfig.Plugin.Customize.ENHANCE_FILE); + if (file.exists() && file.isFile()) { + NodeList classNodeList = resolverFileClassDesc(file); + resolverClassNodeList(classNodeList, customizeMethods); + } + RESOLVED_FILE_CONFIGURATIONS = customizeMethods; + } finally { + RESOLVED_FILE_LOCK.unlock(); + } + return RESOLVED_FILE_CONFIGURATIONS; } /** From cb764a7849ab9210711feda1a7fc5e5a30c1d1a9 Mon Sep 17 00:00:00 2001 From: Zixin Zhou Date: Fri, 29 Nov 2024 15:29:11 +0800 Subject: [PATCH 040/114] Add empty judgment for constructorInterceptPoint (#732) --- CHANGES.md | 1 + .../enhance/ClassEnhancePluginDefine.java | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8275c7e0fa..0e7dd67ab7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ Release Notes. * Add async-profiler feature for performance analysis * Support db.instance tag,db.collection tag and AggregateOperation span for mongodb plugin(3.x/4.x) * Improve CustomizeConfiguration by avoiding repeatedly resolve file config +* Add empty judgment for constructorInterceptPoint All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java index f38ddfc5a8..b595d89e92 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java @@ -112,17 +112,20 @@ protected DynamicType.Builder enhanceInstance(TypeDescription typeDescription */ if (existedConstructorInterceptPoint) { for (ConstructorInterceptPoint constructorInterceptPoint : constructorInterceptPoints) { + String constructorInterceptor = constructorInterceptPoint.getConstructorInterceptor(); + if (StringUtil.isEmpty(constructorInterceptor)) { + throw new EnhanceException("no InstanceConstructorInterceptor define to enhance class " + enhanceOriginClassName); + } if (isBootstrapInstrumentation()) { newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()) - .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration() - .to(BootstrapInstrumentBoost - .forInternalDelegateClass(constructorInterceptPoint - .getConstructorInterceptor())))); + .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration() + .to(BootstrapInstrumentBoost + .forInternalDelegateClass(constructorInterceptor)))); } else { newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()) - .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration() - .to(new ConstructorInter(getPluginName(), constructorInterceptPoint - .getConstructorInterceptor(), classLoader), delegateNamingResolver.resolve(constructorInterceptPoint)))); + .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration() + .to(new ConstructorInter(getPluginName(), constructorInterceptor, classLoader), + delegateNamingResolver.resolve(constructorInterceptPoint)))); } } } From 26ef911aea908759795bb6f5f2f6be56370d30cc Mon Sep 17 00:00:00 2001 From: zhengziyi0117 <91662408+zhengziyi0117@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:12:12 +0800 Subject: [PATCH 041/114] fix: async profiler max duration && reduce memory allocation when sending jfr (#733) --- .../apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java | 2 +- .../org/apache/skywalking/apm/agent/core/conf/Config.java | 4 ++-- apm-sniffer/config/agent.config | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java index 46a25c4cc2..be5af4c360 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/asyncprofiler/AsyncProfilerDataSender.java @@ -100,6 +100,7 @@ public void sendData(AsyncProfilerTask task, File dumpFile) throws IOException, GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS ).collect(new ClientResponseObserver() { ClientCallStreamObserver requestStream; + final byte[] buf = new byte[DATA_CHUNK_SIZE]; @Override public void beforeStart(ClientCallStreamObserver requestStream) { @@ -111,7 +112,6 @@ public void onNext(AsyncProfilerCollectionResponse value) { if (AsyncProfilingStatus.TERMINATED_BY_OVERSIZE.equals(value.getType())) { LOGGER.warn("JFR is too large to be received by the oap server"); } else { - byte[] buf = new byte[DATA_CHUNK_SIZE]; try { int bytesRead; while ((bytesRead = fileInputStream.read(buf)) != -1) { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java index fe2b7448e1..373ff40a0d 100755 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java @@ -262,9 +262,9 @@ public static class AsyncProfiler { /** * Max execution time(second) for the Async Profiler. The task will be stopped even if a longer time is specified. - * default 10min. + * default 20min. */ - public static int MAX_DURATION = 600; + public static int MAX_DURATION = 1200; /** * Path for the JFR outputs from the Async Profiler. diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index 0ceb658627..695e47349f 100755 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -166,8 +166,8 @@ profile.dump_max_stack_depth=${SW_AGENT_PROFILE_DUMP_MAX_STACK_DEPTH:500} profile.snapshot_transport_buffer_size=${SW_AGENT_PROFILE_SNAPSHOT_TRANSPORT_BUFFER_SIZE:4500} # If true, async profiler will be enabled when user creates a new async profiler task. If false, it will be disabled. The default value is true. asyncprofiler.active=${SW_AGENT_ASYNC_PROFILER_ACTIVE:true} -# Max execution time(second) for the Async Profiler. The task will be stopped even if a longer time is specified. default 10min. -asyncprofiler.max_duration=${SW_AGENT_ASYNC_PROFILER_MAX_DURATION:600} +# Max execution time(second) for the Async Profiler. The task will be stopped even if a longer time is specified. default 20min. +asyncprofiler.max_duration=${SW_AGENT_ASYNC_PROFILER_MAX_DURATION:1200} # Path for the JFR outputs from the Async Profiler. If the parameter is not empty, the file will be created in the specified directory, otherwise the Files.createTemp method will be used to create the file. asyncprofiler.output_path=${SW_AGENT_ASYNC_PROFILER_OUTPUT_PATH:} # If true, the agent collects and reports metrics to the backend. From 7e200bbbb052f0e03e5b2db09e1b0a4c6cf1d71c Mon Sep 17 00:00:00 2001 From: ruoji <1654388696@qq.com> Date: Wed, 4 Dec 2024 14:33:13 +0800 Subject: [PATCH 042/114] fix: rm tomcat-10x-plugin version (#734) Co-authored-by: Youliang Feng --- apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml index 3581c999e1..b36a087743 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml @@ -26,7 +26,6 @@ 4.0.0 tomcat-10x-plugin - 8.11.0 8 From f63a99277e518e52d3e1831c636c921d8b6aac25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Tue, 10 Dec 2024 09:53:40 +0800 Subject: [PATCH 043/114] Bump up actions/cache to v4 (#735) --- .github/actions/build/action.yml | 2 +- .github/actions/run/action.yml | 2 +- .github/workflows/ci.yaml | 2 +- .github/workflows/publish-docker.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index f233bda2e4..a41636ac28 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -39,7 +39,7 @@ runs: sed -i "/<\/sourceDirectories>/i scenarios\/""${{ inputs.test_case }}""<\/sourceDirectory>" test/plugin/pom.xml echo "::endgroup::" - name: Cache local Maven repository - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-agent-test-${{ hashFiles('**/pom.xml') }} diff --git a/.github/actions/run/action.yml b/.github/actions/run/action.yml index c0d5ba1172..75a7ee9c26 100644 --- a/.github/actions/run/action.yml +++ b/.github/actions/run/action.yml @@ -42,7 +42,7 @@ runs: docker load -i test-containers/skywalking-agent-test-tomcat-1.0.0.tgz fi - name: Cache local Maven repository - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-agent-test-run-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f286166990..20e2bae6d2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -57,7 +57,7 @@ jobs: with: submodules: true - name: Cache local Maven repository - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-ci-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/publish-docker.yaml b/.github/workflows/publish-docker.yaml index 704c05ad86..71597889a3 100644 --- a/.github/workflows/publish-docker.yaml +++ b/.github/workflows/publish-docker.yaml @@ -36,7 +36,7 @@ jobs: with: submodules: true - name: Cache local Maven repository - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-publish-docker-${{ hashFiles('**/pom.xml') }} From 18e971c48e97b45d8b10b12b3977ee09e086f8b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Wed, 11 Dec 2024 11:49:46 +0800 Subject: [PATCH 044/114] Bump gRPC and netty. (#737) --- CHANGES.md | 2 ++ apm-protocol/apm-network/pom.xml | 5 +++++ dist-material/LICENSE | 4 ++-- pom.xml | 10 +++++----- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0e7dd67ab7..56c5131421 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,8 @@ Release Notes. * Support db.instance tag,db.collection tag and AggregateOperation span for mongodb plugin(3.x/4.x) * Improve CustomizeConfiguration by avoiding repeatedly resolve file config * Add empty judgment for constructorInterceptPoint +* Bump up gRPC to 1.68.1 +* Bump up netty to 4.1.115.Final All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-protocol/apm-network/pom.xml b/apm-protocol/apm-network/pom.xml index 195286c43a..3edb1f9c05 100644 --- a/apm-protocol/apm-network/pom.xml +++ b/apm-protocol/apm-network/pom.xml @@ -42,6 +42,11 @@ netty-codec-http2 ${netty.version} + + io.grpc + grpc-core + ${grpc.version} + io.grpc grpc-netty diff --git a/dist-material/LICENSE b/dist-material/LICENSE index f36ccd2177..d763acd590 100755 --- a/dist-material/LICENSE +++ b/dist-material/LICENSE @@ -216,12 +216,12 @@ The following components are provided under the Apache License. See project link The text of each license is the standard Apache 2.0 license. raphw (byte-buddy) 1.14.9: http://bytebuddy.net/ , Apache 2.0 - Google: grpc-java 1.53.0: https://github.com/grpc/grpc-java, Apache 2.0 + Google: grpc-java 1.68.1: https://github.com/grpc/grpc-java, Apache 2.0 Google: gson 2.8.9: https://github.com/google/gson , Apache 2.0 Google: proto-google-common-protos 2.0.1: https://github.com/googleapis/googleapis , Apache 2.0 Google: jsr305 3.0.2: http://central.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.0/jsr305-3.0.0.pom , Apache 2.0 Google: guava 32.0.1: https://github.com/google/guava , Apache 2.0 - netty 4.1.100: https://github.com/netty/netty/blob/4.1/LICENSE.txt, Apache 2.0 + netty 4.1.115: https://github.com/netty/netty/blob/4.1/LICENSE.txt, Apache 2.0 async-profiler 3.0: https://github.com/async-profiler/async-profiler/blob/v3.0/LICENSE, Apache 2.0 ======================================================================== diff --git a/pom.xml b/pom.xml index 1ca1ec9c2a..7071bb6d5c 100755 --- a/pom.xml +++ b/pom.xml @@ -87,13 +87,13 @@ 1.14.9 - 1.53.0 - 4.1.100.Final + 1.68.1 + 4.1.115.Final 2.8.9 - 1.6.2 + 1.7.1 0.6.1 - 3.21.7 - 1.53.0 + 3.25.5 + 1.68.1 2.0.48.Final 1.3.2 3.1 From 26600e76e2c8919c128772e5ff2ab377ce25a095 Mon Sep 17 00:00:00 2001 From: youjie23 <350193107@qq.com> Date: Sun, 15 Dec 2024 19:26:40 +0800 Subject: [PATCH 045/114] Fix CreateAopProxyInterceptor in the Spring core-patch indeed changes the implementation of the Spring AOP proxy (#739) --- CHANGES.md | 1 + .../patch/CreateAopProxyInterceptor.java | 36 ++++- .../patch/CreateAopProxyInterceptorTest.java | 139 +++++++++++++++++- 3 files changed, 164 insertions(+), 12 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 56c5131421..92ace88d30 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ Release Notes. * Add empty judgment for constructorInterceptPoint * Bump up gRPC to 1.68.1 * Bump up netty to 4.1.115.Final +* Fix the `CreateAopProxyInterceptor` in the Spring core-patch to prevent it from changing the implementation of the Spring AOP proxy All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/CreateAopProxyInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/CreateAopProxyInterceptor.java index 97bab4ad33..6e55d80b1a 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/CreateAopProxyInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/CreateAopProxyInterceptor.java @@ -18,12 +18,14 @@ package org.apache.skywalking.apm.plugin.spring.patch; -import java.lang.reflect.Method; 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.springframework.aop.SpringProxy; import org.springframework.aop.framework.AdvisedSupport; +import java.lang.reflect.Method; + /** * CreateAopProxyInterceptor check that the bean has been implement {@link EnhancedInstance}. * if yes, true will be returned. @@ -32,25 +34,45 @@ public class CreateAopProxyInterceptor implements InstanceMethodsAroundIntercept @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { + MethodInterceptResult result) throws Throwable { } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - Object ret) throws Throwable { + Object ret) throws Throwable { AdvisedSupport advisedSupport = (AdvisedSupport) allArguments[0]; - Class targetClass = advisedSupport.getTargetClass(); - if (targetClass != null && EnhancedInstance.class.isAssignableFrom(targetClass)) { - return true; + if (maybeHasUserSuppliedProxyInterfaces(ret)) { + Class targetClass = advisedSupport.getTargetClass(); + if (targetClass != null) { + if (onlyImplementsEnhancedInstance(advisedSupport) || onlyImplementsEnhancedInstanceAndSpringProxy(advisedSupport)) { + return true; + } + } } return ret; } + private boolean maybeHasUserSuppliedProxyInterfaces(Object ret) { + return !(Boolean) ret; + } + + private boolean onlyImplementsEnhancedInstanceAndSpringProxy(AdvisedSupport advisedSupport) { + Class[] ifcs = advisedSupport.getProxiedInterfaces(); + Class targetClass = advisedSupport.getTargetClass(); + return ifcs.length == 2 && EnhancedInstance.class.isAssignableFrom(targetClass) && SpringProxy.class.isAssignableFrom(targetClass); + } + + private boolean onlyImplementsEnhancedInstance(AdvisedSupport advisedSupport) { + Class[] ifcs = advisedSupport.getProxiedInterfaces(); + Class targetClass = advisedSupport.getTargetClass(); + return ifcs.length == 1 && EnhancedInstance.class.isAssignableFrom(targetClass); + } + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t) { + Class[] argumentsTypes, Throwable t) { } } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/test/java/org/apache/skywalking/apm/plugin/spring/patch/CreateAopProxyInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/test/java/org/apache/skywalking/apm/plugin/spring/patch/CreateAopProxyInterceptorTest.java index 12b5c96633..ae513567da 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/test/java/org/apache/skywalking/apm/plugin/spring/patch/CreateAopProxyInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/test/java/org/apache/skywalking/apm/plugin/spring/patch/CreateAopProxyInterceptorTest.java @@ -24,6 +24,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.aop.SpringProxy; import org.springframework.aop.framework.AdvisedSupport; import static org.hamcrest.core.Is.is; @@ -48,18 +49,69 @@ public void setUp() { } @Test - public void testInterceptNormalObject() throws Throwable { - doReturn(Object.class).when(advisedSupport).getTargetClass(); + public void testInterceptClassImplementsNoInterfaces() throws Throwable { + // doReturn(Object.class).when(advisedSupport).getTargetClass(); + // doReturn(Object.class.getInterfaces()).when(advisedSupport).getProxiedInterfaces(); + assertThat(true, is(interceptor.afterMethod(enhancedInstance, null, new Object[] {advisedSupport}, new Class[] {Object.class}, true))); + } + + @Test + public void testInterceptClassImplementsUserSuppliedInterface() throws Throwable { + doReturn(MockClassImplementsUserSuppliedInterface.class).when(advisedSupport).getTargetClass(); + doReturn(MockClassImplementsUserSuppliedInterface.class.getInterfaces()).when(advisedSupport).getProxiedInterfaces(); assertThat(false, is(interceptor.afterMethod(enhancedInstance, null, new Object[] {advisedSupport}, new Class[] {Object.class}, false))); } @Test - public void testInterceptEnhanceInstanceObject() throws Throwable { - doReturn(MockClass.class).when(advisedSupport).getTargetClass(); + public void testInterceptClassImplementsSpringProxy() throws Throwable { + // doReturn(MockClassImplementsSpringProxy.class).when(advisedSupport).getTargetClass(); + // doReturn(MockClassImplementsSpringProxy.class.getInterfaces()).when(advisedSupport).getProxiedInterfaces(); + assertThat(true, is(interceptor.afterMethod(enhancedInstance, null, new Object[] {advisedSupport}, new Class[] {Object.class}, true))); + } + + @Test + public void testInterceptClassImplementsEnhancedInstance() throws Throwable { + doReturn(MockClassImplementsEnhancedInstance.class).when(advisedSupport).getTargetClass(); + doReturn(MockClassImplementsEnhancedInstance.class.getInterfaces()).when(advisedSupport).getProxiedInterfaces(); assertThat(true, is(interceptor.afterMethod(enhancedInstance, null, new Object[] {advisedSupport}, new Class[] {Object.class}, false))); } - private class MockClass implements EnhancedInstance { + @Test + public void testClassImplementsEnhancedInstanceAndUserSuppliedInterface() throws Throwable { + doReturn(MockClassImplementsSpringProxyAndUserSuppliedInterface.class).when(advisedSupport).getTargetClass(); + doReturn(MockClassImplementsSpringProxyAndUserSuppliedInterface.class.getInterfaces()).when(advisedSupport).getProxiedInterfaces(); + assertThat(false, is(interceptor.afterMethod(enhancedInstance, null, new Object[] {advisedSupport}, new Class[] {Object.class}, false))); + } + + @Test + public void testInterceptClassImplementsSpringProxyAndEnhancedInstance() throws Throwable { + doReturn(MockClassImplementsSpringProxyAndEnhancedInstance.class).when(advisedSupport).getTargetClass(); + doReturn(MockClassImplementsSpringProxyAndEnhancedInstance.class.getInterfaces()).when(advisedSupport).getProxiedInterfaces(); + assertThat(true, is(interceptor.afterMethod(enhancedInstance, null, new Object[] {advisedSupport}, new Class[] {Object.class}, false))); + } + + @Test + public void testInterceptClassImplementsSpringProxyAndUserSuppliedInterface() throws Throwable { + doReturn(MockClassImplementsSpringProxyAndUserSuppliedInterface.class).when(advisedSupport).getTargetClass(); + doReturn(MockClassImplementsSpringProxyAndUserSuppliedInterface.class.getInterfaces()).when(advisedSupport).getProxiedInterfaces(); + assertThat(false, is(interceptor.afterMethod(enhancedInstance, null, new Object[] {advisedSupport}, new Class[] {Object.class}, false))); + } + + @Test + public void testInterceptClassImplementsEnhancedInstanceAndUserSuppliedInterface() throws Throwable { + doReturn(MockClassImplementsEnhancedInstanceAndUserSuppliedInterface.class).when(advisedSupport).getTargetClass(); + doReturn(MockClassImplementsEnhancedInstanceAndUserSuppliedInterface.class.getInterfaces()).when(advisedSupport).getProxiedInterfaces(); + assertThat(false, is(interceptor.afterMethod(enhancedInstance, null, new Object[] {advisedSupport}, new Class[] {Object.class}, false))); + } + + @Test + public void testInterceptClassImplementsSpringProxyAndEnhancedInstanceAndUserSuppliedInterface() throws Throwable { + doReturn(MockClassImplementsSpringProxyAndEnhancedInstanceAndUserSuppliedInterface.class).when(advisedSupport).getTargetClass(); + doReturn(MockClassImplementsSpringProxyAndEnhancedInstanceAndUserSuppliedInterface.class.getInterfaces()).when(advisedSupport).getProxiedInterfaces(); + assertThat(false, is(interceptor.afterMethod(enhancedInstance, null, new Object[] {advisedSupport}, new Class[] {Object.class}, false))); + } + + private class MockClassImplementsEnhancedInstance implements EnhancedInstance { @Override public Object getSkyWalkingDynamicField() { @@ -72,4 +124,81 @@ public void setSkyWalkingDynamicField(Object value) { } } + private class MockClassImplementsUserSuppliedInterface implements UserSuppliedInterface { + + @Override + public void methodOfUserSuppliedInterface() { + + } + + } + + private class MockClassImplementsSpringProxy implements SpringProxy { + + } + + private class MockClassImplementsSpringProxyAndEnhancedInstance implements EnhancedInstance, SpringProxy { + + @Override + public Object getSkyWalkingDynamicField() { + return null; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + + } + + } + + private class MockClassImplementsEnhancedInstanceAndUserSuppliedInterface implements EnhancedInstance, UserSuppliedInterface { + + @Override + public Object getSkyWalkingDynamicField() { + return null; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + + } + + @Override + public void methodOfUserSuppliedInterface() { + } + + } + + private class MockClassImplementsSpringProxyAndUserSuppliedInterface implements SpringProxy, UserSuppliedInterface { + + @Override + public void methodOfUserSuppliedInterface() { + } + + } + + private class MockClassImplementsSpringProxyAndEnhancedInstanceAndUserSuppliedInterface implements EnhancedInstance, SpringProxy, UserSuppliedInterface { + + @Override + public Object getSkyWalkingDynamicField() { + return null; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + + } + + @Override + public void methodOfUserSuppliedInterface() { + } + + } + + interface UserSuppliedInterface { + + void methodOfUserSuppliedInterface(); + + } + } From be3d09240a57f95a25a293875f255110b2e9b82b Mon Sep 17 00:00:00 2001 From: yqw570994511 <49865334+yqw570994511@users.noreply.github.com> Date: Mon, 16 Dec 2024 15:03:14 +0800 Subject: [PATCH 046/114] [Feature] Support Tracing for GlobalFilter and GatewayFilter in Gateway (#736) --- CHANGES.md | 1 + .../v20x/GatewayFilterInterceptor.java | 94 +++++ .../cloud/gateway/v20x/define/Constants.java | 4 + .../define/GatewayFilterInstrumentation.java | 64 ++++ .../src/main/resources/skywalking-plugin.def | 3 +- .../v20x/GatewayFilterInterceptorTest.java | 333 ++++++++++++++++++ .../v21x/GatewayFilterInterceptor.java | 94 +++++ .../cloud/gateway/v21x/define/Constants.java | 3 + .../define/GatewayFilterInstrumentation.java | 64 ++++ .../src/main/resources/skywalking-plugin.def | 1 + .../v21x/GatewayFilterInterceptorTest.java | 332 +++++++++++++++++ .../gateway/v3x/GatewayFilterInterceptor.java | 94 +++++ .../define/GatewayFilterInstrumentation.java | 67 ++++ .../src/main/resources/skywalking-plugin.def | 1 + .../v3x/GatewayFilterInterceptorTest.java | 332 +++++++++++++++++ .../gateway/v4x/GatewayFilterInterceptor.java | 94 +++++ .../define/GatewayFilterInstrumentation.java | 67 ++++ .../src/main/resources/skywalking-plugin.def | 1 + .../v4x/GatewayFilterInterceptorTest.java | 332 +++++++++++++++++ .../config/expectedData.yaml | 26 +- .../config/expectedData.yaml | 46 ++- .../config/expectedData.yaml | 4 +- .../config/expectedData.yaml | 46 ++- .../config/expectedData.yaml | 46 ++- 24 files changed, 2110 insertions(+), 39 deletions(-) create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/GatewayFilterInterceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/GatewayFilterInstrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/GatewayFilterInterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/GatewayFilterInterceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/GatewayFilterInstrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/GatewayFilterInterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/GatewayFilterInterceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/GatewayFilterInstrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/GatewayFilterInterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/GatewayFilterInterceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/GatewayFilterInstrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/GatewayFilterInterceptorTest.java diff --git a/CHANGES.md b/CHANGES.md index 92ace88d30..20a83148ef 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ Release Notes. * Bump up gRPC to 1.68.1 * Bump up netty to 4.1.115.Final * Fix the `CreateAopProxyInterceptor` in the Spring core-patch to prevent it from changing the implementation of the Spring AOP proxy +* Support Tracing for GlobalFilter and GatewayFilter in Spring Gateway All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/GatewayFilterInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/GatewayFilterInterceptor.java new file mode 100644 index 0000000000..b5174773c3 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/GatewayFilterInterceptor.java @@ -0,0 +1,94 @@ +/* + * 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.spring.cloud.gateway.v20x; + +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.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.ServerWebExchangeDecorator; +import org.springframework.web.server.adapter.DefaultServerWebExchange; + +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.skywalking.apm.network.trace.component.ComponentsDefine.SPRING_CLOUD_GATEWAY; + +public class GatewayFilterInterceptor implements InstanceMethodsAroundInterceptor { + + private static final ThreadLocal STACK_DEEP = ThreadLocal.withInitial(() -> new AtomicInteger(0)); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + if (isEntry()) { + ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; + + EnhancedInstance enhancedInstance = getInstance(exchange); + + AbstractSpan span = ContextManager.createLocalSpan("SpringCloudGateway/GatewayFilter"); + if (enhancedInstance != null && enhancedInstance.getSkyWalkingDynamicField() != null) { + ContextManager.continued((ContextSnapshot) enhancedInstance.getSkyWalkingDynamicField()); + } + span.setComponent(SPRING_CLOUD_GATEWAY); + } + } + + public static EnhancedInstance getInstance(Object o) { + EnhancedInstance instance = null; + if (o instanceof DefaultServerWebExchange) { + instance = (EnhancedInstance) o; + } else if (o instanceof ServerWebExchangeDecorator) { + ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate(); + return getInstance(delegate); + } + return instance; + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (isExit()) { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + } + + private boolean isEntry() { + return STACK_DEEP.get().getAndIncrement() == 0; + } + + private boolean isExit() { + boolean isExit = STACK_DEEP.get().decrementAndGet() == 0; + if (isExit) { + STACK_DEEP.remove(); + } + return isExit; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/Constants.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/Constants.java index 450699c959..f20a1c22a6 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/Constants.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/Constants.java @@ -29,4 +29,8 @@ public interface Constants { // HttpClientRequest String INTERCEPT_CLASS_HTTP_CLIENT_REQUEST = "reactor.ipc.netty.http.client.HttpClientRequest"; String HTTPCLIENT_REQUEST_HEADERS_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v20x.HttpclientRequestHeadersInterceptor"; + + // GatewayFilter + String INTERCEPT_CLASS_GATEWAY_FILTER = "org.springframework.cloud.gateway.filter.GatewayFilter"; + String GATEWAY_FILTER_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v20x.GatewayFilterInterceptor"; } diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/GatewayFilterInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/GatewayFilterInstrumentation.java new file mode 100644 index 0000000000..3e303d8df3 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/GatewayFilterInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.cloud.gateway.v20x.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.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 GatewayFilterInstrumentation extends AbstractGateway200EnhancePluginDefine { + + @Override + protected ClassMatch enhanceClass() { + return HierarchyMatch.byHierarchyMatch(Constants.INTERCEPT_CLASS_GATEWAY_FILTER); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("filter").and( + takesArgumentWithType(0, "org.springframework.web.server.ServerWebExchange")); + } + + @Override + public String getMethodsInterceptor() { + return Constants.GATEWAY_FILTER_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/resources/skywalking-plugin.def index 4bd0c3f419..0e4bf641bd 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/resources/skywalking-plugin.def @@ -18,4 +18,5 @@ spring-cloud-gateway-2.0.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway spring-cloud-gateway-2.0.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v20x.define.HttpClientInstrumentation spring-cloud-gateway-2.0.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v20x.define.HttpClientRequestInstrumentation spring-cloud-gateway-2.0.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v20x.define.ServerWebExchangeInstrumentation -spring-cloud-gateway-2.0.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v20x.define.DispatcherHandlerInstrumentation \ No newline at end of file +spring-cloud-gateway-2.0.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v20x.define.DispatcherHandlerInstrumentation +spring-cloud-gateway-2.0.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v20x.define.GatewayFilterInstrumentation \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/GatewayFilterInterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/GatewayFilterInterceptorTest.java new file mode 100644 index 0000000000..3cd7bc8705 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/GatewayFilterInterceptorTest.java @@ -0,0 +1,333 @@ +/* + * 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.spring.cloud.gateway.v20x; + +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.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; + +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.springframework.context.ApplicationContext; +import org.springframework.context.i18n.LocaleContext; +import org.springframework.http.codec.multipart.Part; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebSession; +import reactor.core.publisher.Mono; + +import java.security.Principal; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +@RunWith(TracingSegmentRunner.class) +public class GatewayFilterInterceptorTest { + + private static final String GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME = "SpringCloudGateway/GatewayFilter"; + + private static class ServerWebExchangeEnhancedInstance implements ServerWebExchange, EnhancedInstance { + private ContextSnapshot snapshot; + Map attributes = new HashMap<>(); + + @Override + public Object getSkyWalkingDynamicField() { + return snapshot; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.snapshot = (ContextSnapshot) value; + } + + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + } + + private final ServerWebExchangeEnhancedInstance enhancedInstance = new ServerWebExchangeEnhancedInstance(); + private final GatewayFilterInterceptor interceptor = new GatewayFilterInterceptor(); + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Before + public void setUp() throws Exception { + } + + private final ServerWebExchange exchange = new ServerWebExchange() { + Map attributes = new HashMap<>(); + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + }; + + @Test + public void testInterceptOnlyOnce() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{exchange}, null, null); + Assert.assertTrue(ContextManager.isActive()); + AbstractSpan activeSpan = ContextManager.activeSpan(); + Assert.assertTrue(activeSpan instanceof AbstractTracingSpan); + Assert.assertEquals(activeSpan.getOperationName(), GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + + } + + @Test + public void testNestedInterception() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithNullDynamicField() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithContextSnapshot() throws Throwable { + final AbstractSpan entrySpan = ContextManager.createEntrySpan("/get", null); + SpanLayer.asHttp(entrySpan); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + enhancedInstance.setSkyWalkingDynamicField(ContextManager.capture()); + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + ContextManager.stopSpan(entrySpan); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 2); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + SpanAssert.assertComponent(spans.get(1), ComponentsDefine.SPRING_WEBFLUX); + SpanAssert.assertLayer(spans.get(1), SpanLayer.HTTP); + } + +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/GatewayFilterInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/GatewayFilterInterceptor.java new file mode 100644 index 0000000000..18b93a08d1 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/GatewayFilterInterceptor.java @@ -0,0 +1,94 @@ +/* + * 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.spring.cloud.gateway.v21x; + +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.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.ServerWebExchangeDecorator; +import org.springframework.web.server.adapter.DefaultServerWebExchange; + +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.skywalking.apm.network.trace.component.ComponentsDefine.SPRING_CLOUD_GATEWAY; + +public class GatewayFilterInterceptor implements InstanceMethodsAroundInterceptor { + + private static final ThreadLocal STACK_DEEP = ThreadLocal.withInitial(() -> new AtomicInteger(0)); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + if (isEntry()) { + ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; + + EnhancedInstance enhancedInstance = getInstance(exchange); + + AbstractSpan span = ContextManager.createLocalSpan("SpringCloudGateway/GatewayFilter"); + if (enhancedInstance != null && enhancedInstance.getSkyWalkingDynamicField() != null) { + ContextManager.continued((ContextSnapshot) enhancedInstance.getSkyWalkingDynamicField()); + } + span.setComponent(SPRING_CLOUD_GATEWAY); + } + } + + public static EnhancedInstance getInstance(Object o) { + EnhancedInstance instance = null; + if (o instanceof DefaultServerWebExchange) { + instance = (EnhancedInstance) o; + } else if (o instanceof ServerWebExchangeDecorator) { + ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate(); + return getInstance(delegate); + } + return instance; + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (isExit()) { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + } + + private boolean isEntry() { + return STACK_DEEP.get().getAndIncrement() == 0; + } + + private boolean isExit() { + boolean isExit = STACK_DEEP.get().decrementAndGet() == 0; + if (isExit) { + STACK_DEEP.remove(); + } + return isExit; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/Constants.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/Constants.java index 1dbb09ff16..5c88626779 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/Constants.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/Constants.java @@ -33,4 +33,7 @@ public interface Constants { String INTERCEPT_CLASS_TCP_CLIENT = "reactor.netty.tcp.TcpClient"; String TCP_CLIENT_CONSTRUCTOR_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.TcpClientConstructorInterceptor"; + // GatewayFilter + String INTERCEPT_CLASS_GATEWAY_FILTER = "org.springframework.cloud.gateway.filter.GatewayFilter"; + String GATEWAY_FILTER_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.GatewayFilterInterceptor"; } diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/GatewayFilterInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/GatewayFilterInstrumentation.java new file mode 100644 index 0000000000..62d562c0b0 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/GatewayFilterInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.cloud.gateway.v21x.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.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 GatewayFilterInstrumentation extends AbstractGateway210EnhancePluginDefine { + + @Override + protected ClassMatch enhanceClass() { + return HierarchyMatch.byHierarchyMatch(Constants.INTERCEPT_CLASS_GATEWAY_FILTER); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("filter").and( + takesArgumentWithType(0, "org.springframework.web.server.ServerWebExchange")); + } + + @Override + public String getMethodsInterceptor() { + return Constants.GATEWAY_FILTER_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/resources/skywalking-plugin.def index 9929db9240..8ce727bb5d 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/resources/skywalking-plugin.def @@ -19,3 +19,4 @@ spring-cloud-gateway-2.1.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway spring-cloud-gateway-2.1.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define.TcpClientInstrumentation spring-cloud-gateway-2.1.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define.ServerWebExchangeInstrumentation spring-cloud-gateway-2.1.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define.DispatcherHandlerInstrumentation +spring-cloud-gateway-2.1.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x.define.GatewayFilterInstrumentation diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/GatewayFilterInterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/GatewayFilterInterceptorTest.java new file mode 100644 index 0000000000..c2250e3beb --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/GatewayFilterInterceptorTest.java @@ -0,0 +1,332 @@ +/* + * 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.spring.cloud.gateway.v21x; + +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.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.springframework.context.ApplicationContext; +import org.springframework.context.i18n.LocaleContext; +import org.springframework.http.codec.multipart.Part; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebSession; +import reactor.core.publisher.Mono; + +import java.security.Principal; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +@RunWith(TracingSegmentRunner.class) +public class GatewayFilterInterceptorTest { + + private static final String GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME = "SpringCloudGateway/GatewayFilter"; + + private static class ServerWebExchangeEnhancedInstance implements ServerWebExchange, EnhancedInstance { + private ContextSnapshot snapshot; + Map attributes = new HashMap<>(); + + @Override + public Object getSkyWalkingDynamicField() { + return snapshot; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.snapshot = (ContextSnapshot) value; + } + + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + } + + private final ServerWebExchangeEnhancedInstance enhancedInstance = new ServerWebExchangeEnhancedInstance(); + private final GatewayFilterInterceptor interceptor = new GatewayFilterInterceptor(); + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Before + public void setUp() throws Exception { + } + + private final ServerWebExchange exchange = new ServerWebExchange() { + Map attributes = new HashMap<>(); + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + }; + + @Test + public void testInterceptOnlyOnce() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{exchange}, null, null); + Assert.assertTrue(ContextManager.isActive()); + AbstractSpan activeSpan = ContextManager.activeSpan(); + Assert.assertTrue(activeSpan instanceof AbstractTracingSpan); + Assert.assertEquals(activeSpan.getOperationName(), GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + + } + + @Test + public void testNestedInterception() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithNullDynamicField() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithContextSnapshot() throws Throwable { + final AbstractSpan entrySpan = ContextManager.createEntrySpan("/get", null); + SpanLayer.asHttp(entrySpan); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + enhancedInstance.setSkyWalkingDynamicField(ContextManager.capture()); + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + ContextManager.stopSpan(entrySpan); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 2); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + SpanAssert.assertComponent(spans.get(1), ComponentsDefine.SPRING_WEBFLUX); + SpanAssert.assertLayer(spans.get(1), SpanLayer.HTTP); + } + +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/GatewayFilterInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/GatewayFilterInterceptor.java new file mode 100644 index 0000000000..133424539b --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/GatewayFilterInterceptor.java @@ -0,0 +1,94 @@ +/* + * 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.spring.cloud.gateway.v3x; + +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.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.ServerWebExchangeDecorator; +import org.springframework.web.server.adapter.DefaultServerWebExchange; + +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.skywalking.apm.network.trace.component.ComponentsDefine.SPRING_CLOUD_GATEWAY; + +public class GatewayFilterInterceptor implements InstanceMethodsAroundInterceptor { + + private static final ThreadLocal STACK_DEEP = ThreadLocal.withInitial(() -> new AtomicInteger(0)); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + if (isEntry()) { + ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; + + EnhancedInstance enhancedInstance = getInstance(exchange); + + AbstractSpan span = ContextManager.createLocalSpan("SpringCloudGateway/GatewayFilter"); + if (enhancedInstance != null && enhancedInstance.getSkyWalkingDynamicField() != null) { + ContextManager.continued((ContextSnapshot) enhancedInstance.getSkyWalkingDynamicField()); + } + span.setComponent(SPRING_CLOUD_GATEWAY); + } + } + + public static EnhancedInstance getInstance(Object o) { + EnhancedInstance instance = null; + if (o instanceof DefaultServerWebExchange) { + instance = (EnhancedInstance) o; + } else if (o instanceof ServerWebExchangeDecorator) { + ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate(); + return getInstance(delegate); + } + return instance; + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (isExit()) { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + } + + private boolean isEntry() { + return STACK_DEEP.get().getAndIncrement() == 0; + } + + private boolean isExit() { + boolean isExit = STACK_DEEP.get().decrementAndGet() == 0; + if (isExit) { + STACK_DEEP.remove(); + } + return isExit; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/GatewayFilterInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/GatewayFilterInstrumentation.java new file mode 100644 index 0000000000..644d844f35 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/GatewayFilterInstrumentation.java @@ -0,0 +1,67 @@ +/* + * 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.spring.cloud.gateway.v3x.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.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 GatewayFilterInstrumentation extends AbstractGatewayV3EnhancePluginDefine { + + private static final String INTERCEPT_CLASS_GATEWAY_FILTER = "org.springframework.cloud.gateway.filter.GatewayFilter"; + private static final String GATEWAY_FILTER_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.GatewayFilterInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return HierarchyMatch.byHierarchyMatch(INTERCEPT_CLASS_GATEWAY_FILTER); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("filter").and( + takesArgumentWithType(0, "org.springframework.web.server.ServerWebExchange")); + } + + @Override + public String getMethodsInterceptor() { + return GATEWAY_FILTER_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/resources/skywalking-plugin.def index ba4b480501..10525a931a 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/resources/skywalking-plugin.def @@ -18,3 +18,4 @@ spring-cloud-gateway-3.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v spring-cloud-gateway-3.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.NettyRoutingFilterInstrumentation spring-cloud-gateway-3.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.ServerWebExchangeInstrumentation spring-cloud-gateway-3.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.DispatcherHandlerInstrumentation +spring-cloud-gateway-3.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.GatewayFilterInstrumentation diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/GatewayFilterInterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/GatewayFilterInterceptorTest.java new file mode 100644 index 0000000000..db0e0e3174 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/GatewayFilterInterceptorTest.java @@ -0,0 +1,332 @@ +/* + * 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.spring.cloud.gateway.v3x; + +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.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.springframework.context.ApplicationContext; +import org.springframework.context.i18n.LocaleContext; +import org.springframework.http.codec.multipart.Part; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebSession; +import reactor.core.publisher.Mono; + +import java.security.Principal; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +@RunWith(TracingSegmentRunner.class) +public class GatewayFilterInterceptorTest { + + private static final String GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME = "SpringCloudGateway/GatewayFilter"; + + private static class ServerWebExchangeEnhancedInstance implements ServerWebExchange, EnhancedInstance { + private ContextSnapshot snapshot; + Map attributes = new HashMap<>(); + + @Override + public Object getSkyWalkingDynamicField() { + return snapshot; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.snapshot = (ContextSnapshot) value; + } + + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + } + + private final ServerWebExchangeEnhancedInstance enhancedInstance = new ServerWebExchangeEnhancedInstance(); + private final GatewayFilterInterceptor interceptor = new GatewayFilterInterceptor(); + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Before + public void setUp() throws Exception { + } + + private final ServerWebExchange exchange = new ServerWebExchange() { + Map attributes = new HashMap<>(); + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + }; + + @Test + public void testInterceptOnlyOnce() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{exchange}, null, null); + Assert.assertTrue(ContextManager.isActive()); + AbstractSpan activeSpan = ContextManager.activeSpan(); + Assert.assertTrue(activeSpan instanceof AbstractTracingSpan); + Assert.assertEquals(activeSpan.getOperationName(), GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + + } + + @Test + public void testNestedInterception() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithNullDynamicField() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithContextSnapshot() throws Throwable { + final AbstractSpan entrySpan = ContextManager.createEntrySpan("/get", null); + SpanLayer.asHttp(entrySpan); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + enhancedInstance.setSkyWalkingDynamicField(ContextManager.capture()); + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + ContextManager.stopSpan(entrySpan); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 2); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + SpanAssert.assertComponent(spans.get(1), ComponentsDefine.SPRING_WEBFLUX); + SpanAssert.assertLayer(spans.get(1), SpanLayer.HTTP); + } + +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/GatewayFilterInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/GatewayFilterInterceptor.java new file mode 100644 index 0000000000..233eb24ea7 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/GatewayFilterInterceptor.java @@ -0,0 +1,94 @@ +/* + * 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.spring.cloud.gateway.v4x; + +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.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.ServerWebExchangeDecorator; +import org.springframework.web.server.adapter.DefaultServerWebExchange; + +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.skywalking.apm.network.trace.component.ComponentsDefine.SPRING_CLOUD_GATEWAY; + +public class GatewayFilterInterceptor implements InstanceMethodsAroundInterceptor { + + private static final ThreadLocal STACK_DEEP = ThreadLocal.withInitial(() -> new AtomicInteger(0)); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + if (isEntry()) { + ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; + + EnhancedInstance enhancedInstance = getInstance(exchange); + + AbstractSpan span = ContextManager.createLocalSpan("SpringCloudGateway/GatewayFilter"); + if (enhancedInstance != null && enhancedInstance.getSkyWalkingDynamicField() != null) { + ContextManager.continued((ContextSnapshot) enhancedInstance.getSkyWalkingDynamicField()); + } + span.setComponent(SPRING_CLOUD_GATEWAY); + } + } + + public static EnhancedInstance getInstance(Object o) { + EnhancedInstance instance = null; + if (o instanceof DefaultServerWebExchange) { + instance = (EnhancedInstance) o; + } else if (o instanceof ServerWebExchangeDecorator) { + ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate(); + return getInstance(delegate); + } + return instance; + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (isExit()) { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + } + + private boolean isEntry() { + return STACK_DEEP.get().getAndIncrement() == 0; + } + + private boolean isExit() { + boolean isExit = STACK_DEEP.get().decrementAndGet() == 0; + if (isExit) { + STACK_DEEP.remove(); + } + return isExit; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/GatewayFilterInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/GatewayFilterInstrumentation.java new file mode 100644 index 0000000000..5a61b89ac1 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/GatewayFilterInstrumentation.java @@ -0,0 +1,67 @@ +/* + * 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.spring.cloud.gateway.v4x.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.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 GatewayFilterInstrumentation extends AbstractGatewayV4EnhancePluginDefine { + + private static final String INTERCEPT_CLASS_GATEWAY_FILTER = "org.springframework.cloud.gateway.filter.GatewayFilter"; + private static final String GATEWAY_FILTER_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.GatewayFilterInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return HierarchyMatch.byHierarchyMatch(INTERCEPT_CLASS_GATEWAY_FILTER); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("filter").and( + takesArgumentWithType(0, "org.springframework.web.server.ServerWebExchange")); + } + + @Override + public String getMethodsInterceptor() { + return GATEWAY_FILTER_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/resources/skywalking-plugin.def index 5cbcbfcdd8..a335a6b336 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/resources/skywalking-plugin.def @@ -18,3 +18,4 @@ spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.NettyRoutingFilterInstrumentation spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.ServerWebExchangeInstrumentation spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.DispatcherHandlerInstrumentation +spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.GatewayFilterInstrumentation diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/GatewayFilterInterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/GatewayFilterInterceptorTest.java new file mode 100644 index 0000000000..d59c63cd17 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/GatewayFilterInterceptorTest.java @@ -0,0 +1,332 @@ +/* + * 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.spring.cloud.gateway.v4x; + +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.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.springframework.context.ApplicationContext; +import org.springframework.context.i18n.LocaleContext; +import org.springframework.http.codec.multipart.Part; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebSession; +import reactor.core.publisher.Mono; + +import java.security.Principal; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +@RunWith(TracingSegmentRunner.class) +public class GatewayFilterInterceptorTest { + + private static final String GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME = "SpringCloudGateway/GatewayFilter"; + + private static class ServerWebExchangeEnhancedInstance implements ServerWebExchange, EnhancedInstance { + private ContextSnapshot snapshot; + Map attributes = new HashMap<>(); + + @Override + public Object getSkyWalkingDynamicField() { + return snapshot; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.snapshot = (ContextSnapshot) value; + } + + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + } + + private final ServerWebExchangeEnhancedInstance enhancedInstance = new ServerWebExchangeEnhancedInstance(); + private final GatewayFilterInterceptor interceptor = new GatewayFilterInterceptor(); + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Before + public void setUp() throws Exception { + } + + private final ServerWebExchange exchange = new ServerWebExchange() { + Map attributes = new HashMap<>(); + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + }; + + @Test + public void testInterceptOnlyOnce() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{exchange}, null, null); + Assert.assertTrue(ContextManager.isActive()); + AbstractSpan activeSpan = ContextManager.activeSpan(); + Assert.assertTrue(activeSpan instanceof AbstractTracingSpan); + Assert.assertEquals(activeSpan.getOperationName(), GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + + } + + @Test + public void testNestedInterception() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithNullDynamicField() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithContextSnapshot() throws Throwable { + final AbstractSpan entrySpan = ContextManager.createEntrySpan("/get", null); + SpanLayer.asHttp(entrySpan); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + enhancedInstance.setSkyWalkingDynamicField(ContextManager.capture()); + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + ContextManager.stopSpan(entrySpan); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 2); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + SpanAssert.assertComponent(spans.get(1), ComponentsDefine.SPRING_WEBFLUX); + SpanAssert.assertLayer(spans.get(1), SpanLayer.HTTP); + } + +} diff --git a/test/plugin/scenarios/gateway-2.0.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-2.0.x-scenario/config/expectedData.yaml index 8373df690b..d20a2486bc 100644 --- a/test/plugin/scenarios/gateway-2.0.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/gateway-2.0.x-scenario/config/expectedData.yaml @@ -34,8 +34,8 @@ segmentItems: - {key: http.method, value: GET} - {key: http.status_code, value: '200'} refs: - - {parentEndpoint: SpringCloudGateway/RoutingFilter, networkAddress: 'localhost:18070', - refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + - {parentEndpoint: SpringCloudGateway/GatewayFilter, networkAddress: 'localhost:18070', + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} skipAnalysis: 'false' - serviceName: gateway-projectA-scenario @@ -61,8 +61,8 @@ segmentItems: - segmentId: not null spans: - operationName: SpringCloudGateway/sendRequest - parentSpanId: 0 - spanId: 1 + parentSpanId: 1 + spanId: 2 spanLayer: Http startTime: nq 0 endTime: nq 0 @@ -75,8 +75,8 @@ segmentItems: - {key: http.status_code, value: '200'} skipAnalysis: 'false' - operationName: SpringCloudGateway/RoutingFilter - parentSpanId: -1 - spanId: 0 + parentSpanId: 0 + spanId: 1 startTime: nq 0 endTime: nq 0 componentId: 61 @@ -88,3 +88,17 @@ segmentItems: parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} skipAnalysis: 'false' + - operationName: SpringCloudGateway/GatewayFilter + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: '/provider/b/testcase', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/gateway-2.1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-2.1.x-scenario/config/expectedData.yaml index c312b744ab..7eecbf2365 100644 --- a/test/plugin/scenarios/gateway-2.1.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/gateway-2.1.x-scenario/config/expectedData.yaml @@ -54,8 +54,8 @@ segmentItems: - {key: http.method, value: GET} - {key: http.status_code, value: '200'} refs: - - {parentEndpoint: SpringCloudGateway/RoutingFilter, networkAddress: 'localhost:18070', - refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + - {parentEndpoint: SpringCloudGateway/GatewayFilter, networkAddress: 'localhost:18070', + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} skipAnalysis: 'false' - serviceName: gateway-projectA-scenario @@ -76,8 +76,8 @@ segmentItems: - segmentId: not null spans: - operationName: SpringCloudGateway/sendRequest - parentSpanId: 0 - spanId: 1 + parentSpanId: 1 + spanId: 2 spanLayer: Http startTime: nq 0 endTime: nq 0 @@ -95,8 +95,8 @@ segmentItems: - { key: message, value: not null } - { key: stack, value: not null } - operationName: SpringCloudGateway/RoutingFilter - parentSpanId: -1 - spanId: 0 + parentSpanId: 0 + spanId: 1 startTime: nq 0 endTime: nq 0 componentId: 61 @@ -106,11 +106,23 @@ segmentItems: parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null } skipAnalysis: 'false' + - operationName: SpringCloudGateway/GatewayFilter + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + spanType: Local + refs: + - { parentEndpoint: '/provider/timeout/error', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + skipAnalysis: 'false' - segmentId: not null spans: - operationName: SpringCloudGateway/sendRequest - parentSpanId: 0 - spanId: 1 + parentSpanId: 1 + spanId: 2 spanLayer: Http startTime: nq 0 endTime: nq 0 @@ -123,8 +135,8 @@ segmentItems: - {key: http.status_code, value: '200'} skipAnalysis: 'false' - operationName: SpringCloudGateway/RoutingFilter - parentSpanId: -1 - spanId: 0 + parentSpanId: 0 + spanId: 1 startTime: nq 0 endTime: nq 0 componentId: 61 @@ -136,6 +148,20 @@ segmentItems: parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} skipAnalysis: 'false' + - operationName: SpringCloudGateway/GatewayFilter + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: '/provider/b/testcase', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' - segmentId: not null spans: - operationName: /provider/b/testcase diff --git a/test/plugin/scenarios/gateway-3.x-filter-context-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-3.x-filter-context-scenario/config/expectedData.yaml index 61852cba38..6a052d28fd 100644 --- a/test/plugin/scenarios/gateway-3.x-filter-context-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/gateway-3.x-filter-context-scenario/config/expectedData.yaml @@ -43,8 +43,8 @@ segmentItems: - {key: http.method, value: GET} - {key: http.status_code, value: '200'} refs: - - {parentEndpoint: SpringCloudGateway/RoutingFilter, networkAddress: 'localhost:18070', - refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + - {parentEndpoint: SpringCloudGateway/GatewayFilter, networkAddress: 'localhost:18070', + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} skipAnalysis: 'false' - serviceName: gateway-projectA-scenario diff --git a/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml index 70df54e93f..7a883f6261 100644 --- a/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml @@ -54,8 +54,8 @@ segmentItems: - {key: http.method, value: GET} - {key: http.status_code, value: '200'} refs: - - {parentEndpoint: SpringCloudGateway/RoutingFilter, networkAddress: 'localhost:18070', - refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + - {parentEndpoint: SpringCloudGateway/GatewayFilter, networkAddress: 'localhost:18070', + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} skipAnalysis: 'false' - serviceName: gateway-projectA-scenario @@ -76,8 +76,8 @@ segmentItems: - segmentId: not null spans: - operationName: SpringCloudGateway/sendRequest - parentSpanId: 0 - spanId: 1 + parentSpanId: 1 + spanId: 2 spanLayer: Http startTime: nq 0 endTime: nq 0 @@ -95,8 +95,8 @@ segmentItems: - { key: message, value: not null } - { key: stack, value: not null} - operationName: SpringCloudGateway/RoutingFilter - parentSpanId: -1 - spanId: 0 + parentSpanId: 0 + spanId: 1 startTime: nq 0 endTime: nq 0 componentId: 61 @@ -106,11 +106,23 @@ segmentItems: parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null } skipAnalysis: 'false' + - operationName: SpringCloudGateway/GatewayFilter + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + spanType: Local + refs: + - { parentEndpoint: '/provider/timeout/error', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + skipAnalysis: 'false' - segmentId: not null spans: - operationName: SpringCloudGateway/sendRequest - parentSpanId: 0 - spanId: 1 + parentSpanId: 1 + spanId: 2 spanLayer: Http startTime: nq 0 endTime: nq 0 @@ -123,8 +135,8 @@ segmentItems: - {key: http.status_code, value: '200'} skipAnalysis: 'false' - operationName: SpringCloudGateway/RoutingFilter - parentSpanId: -1 - spanId: 0 + parentSpanId: 0 + spanId: 1 startTime: nq 0 endTime: nq 0 componentId: 61 @@ -136,6 +148,20 @@ segmentItems: parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} skipAnalysis: 'false' + - operationName: SpringCloudGateway/GatewayFilter + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: '/provider/b/testcase', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' - segmentId: not null spans: - operationName: /provider/b/testcase diff --git a/test/plugin/scenarios/gateway-4.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-4.x-scenario/config/expectedData.yaml index 70df54e93f..7a883f6261 100644 --- a/test/plugin/scenarios/gateway-4.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/gateway-4.x-scenario/config/expectedData.yaml @@ -54,8 +54,8 @@ segmentItems: - {key: http.method, value: GET} - {key: http.status_code, value: '200'} refs: - - {parentEndpoint: SpringCloudGateway/RoutingFilter, networkAddress: 'localhost:18070', - refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + - {parentEndpoint: SpringCloudGateway/GatewayFilter, networkAddress: 'localhost:18070', + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} skipAnalysis: 'false' - serviceName: gateway-projectA-scenario @@ -76,8 +76,8 @@ segmentItems: - segmentId: not null spans: - operationName: SpringCloudGateway/sendRequest - parentSpanId: 0 - spanId: 1 + parentSpanId: 1 + spanId: 2 spanLayer: Http startTime: nq 0 endTime: nq 0 @@ -95,8 +95,8 @@ segmentItems: - { key: message, value: not null } - { key: stack, value: not null} - operationName: SpringCloudGateway/RoutingFilter - parentSpanId: -1 - spanId: 0 + parentSpanId: 0 + spanId: 1 startTime: nq 0 endTime: nq 0 componentId: 61 @@ -106,11 +106,23 @@ segmentItems: parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null } skipAnalysis: 'false' + - operationName: SpringCloudGateway/GatewayFilter + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + spanType: Local + refs: + - { parentEndpoint: '/provider/timeout/error', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + skipAnalysis: 'false' - segmentId: not null spans: - operationName: SpringCloudGateway/sendRequest - parentSpanId: 0 - spanId: 1 + parentSpanId: 1 + spanId: 2 spanLayer: Http startTime: nq 0 endTime: nq 0 @@ -123,8 +135,8 @@ segmentItems: - {key: http.status_code, value: '200'} skipAnalysis: 'false' - operationName: SpringCloudGateway/RoutingFilter - parentSpanId: -1 - spanId: 0 + parentSpanId: 0 + spanId: 1 startTime: nq 0 endTime: nq 0 componentId: 61 @@ -136,6 +148,20 @@ segmentItems: parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not null, parentService: not null, traceId: not null} skipAnalysis: 'false' + - operationName: SpringCloudGateway/GatewayFilter + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: '/provider/b/testcase', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' - segmentId: not null spans: - operationName: /provider/b/testcase From b4ad5b1960737a04f6f5913fe4bb36816e1a5c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Mon, 16 Dec 2024 17:51:28 +0800 Subject: [PATCH 047/114] Enhance optional plugin docs for Spring Gateway. (#740) --- CHANGES.md | 10 +- .../java-agent/Optional-plugins.md | 14 ++- .../Oracle-Resin-plugins.md | 6 -- .../Spring-annotation-plugin.md | 2 +- .../agent-optional-plugins/spring-gateway.md | 96 +++++++++++++++++++ .../trace-ignore-plugin.md | 4 +- docs/menu.yml | 12 ++- 7 files changed, 129 insertions(+), 15 deletions(-) delete mode 100644 docs/en/setup/service-agent/java-agent/agent-optional-plugins/Oracle-Resin-plugins.md create mode 100644 docs/en/setup/service-agent/java-agent/agent-optional-plugins/spring-gateway.md diff --git a/CHANGES.md b/CHANGES.md index 20a83148ef..edb63bbe9d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,14 +9,20 @@ Release Notes. * Add agent self-observability. * Fix intermittent ClassCircularityError by preloading ThreadLocalRandom since ByteBuddy 1.12.11 * Add witness class/method for resteasy-server plugin(v3/v4/v6) -* Add async-profiler feature for performance analysis +* Add async-profiler feature for performance analysis * Support db.instance tag,db.collection tag and AggregateOperation span for mongodb plugin(3.x/4.x) * Improve CustomizeConfiguration by avoiding repeatedly resolve file config * Add empty judgment for constructorInterceptPoint * Bump up gRPC to 1.68.1 * Bump up netty to 4.1.115.Final -* Fix the `CreateAopProxyInterceptor` in the Spring core-patch to prevent it from changing the implementation of the Spring AOP proxy +* Fix the `CreateAopProxyInterceptor` in the Spring core-patch to prevent it from changing the implementation of the + Spring AOP proxy * Support Tracing for GlobalFilter and GatewayFilter in Spring Gateway +* [doc] Enhance Custom Trace Ignoring Plugin document about conflicts with the plugin of **sampler plugin with CPU + policy** +* [doc] Add Spring Gateway Plugin document +* [doc] Add 4 menu items guiding users to find important notices for Spring Annotation Plugin, Custom Trace Ignoring + Plugin, Kotlin Coroutine Plugin, and Spring Gateway Plugin All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/docs/en/setup/service-agent/java-agent/Optional-plugins.md b/docs/en/setup/service-agent/java-agent/Optional-plugins.md index 8b8a0ec1c3..b8ab3524f9 100644 --- a/docs/en/setup/service-agent/java-agent/Optional-plugins.md +++ b/docs/en/setup/service-agent/java-agent/Optional-plugins.md @@ -8,13 +8,12 @@ Now, we have the following known 2 kinds of optional plugins. These plugins affect the performance or must be used under some conditions, from experiences. So only released in `/optional-plugins` or `/bootstrap-plugins`, copy to `/plugins` in order to make them work. -* [Plugin of tracing Spring annotation beans](agent-optional-plugins/Spring-annotation-plugin.md) -* [Plugin of tracing Oracle and Resin](agent-optional-plugins/Oracle-Resin-plugins.md) +* Plugin of [tracing Spring annotation beans](agent-optional-plugins/Spring-annotation-plugin.md) * [Filter traces through specified endpoint name patterns](agent-optional-plugins/trace-ignore-plugin.md) * Plugin of Gson serialization lib in optional plugin folder. * Plugin of Zookeeper 3.4.x in optional plugin folder. The reason of being optional plugin is, many business irrelevant traces are generated, which cause extra payload to agents and backends. At the same time, those traces may be just heartbeat(s). * [Customize enhance](Customize-enhance-trace.md) Trace methods based on description files, rather than write plugin or change source codes. -* Plugin of Spring Cloud Gateway 2.x and 3.x and 4.x in optional plugin folder. Please only activate this plugin when you install agent in Spring Gateway. +* Plugin of [Spring Cloud Gateway 2.x and 3.x and 4.x](agent-optional-plugins/spring-gateway.md) in optional plugin folder. Please only activate this plugin when you install agent in Spring Gateway. * Plugin of Spring Transaction in optional plugin folder. The reason of being optional plugin is, many local span are generated, which also spend more CPU, memory and network. * [Plugin of Kotlin coroutine](agent-optional-plugins/Kotlin-Coroutine-plugin.md) provides the tracing across coroutines automatically. As it will add local spans to all across routines scenarios, Please assess the performance impact. * Plugin of quartz-scheduler-2.x in the optional plugin folder. The reason for being an optional plugin is, many task scheduling systems are based on quartz-scheduler, this will cause duplicate tracing and link different sub-tasks as they share the same quartz level trigger, such as ElasticJob. @@ -26,11 +25,18 @@ So only released in `/optional-plugins` or `/bootstrap-plugins`, copy to `/plugi * Plugin of fastjson serialization lib in optional plugin folder. * Plugin of jackson serialization lib in optional plugin folder. * Plugin of Apache ShenYu(incubating) Gateway 2.4.x in optional plugin folder. Please only activate this plugin when you install agent in Apache ShenYu Gateway. -* Plugin of trace sampler CPU policy in the optional plugin folder. Please only activate this plugin when you need to disable trace collecting when the agent process CPU usage is too high(over threshold). +* Plugin of sampler plugin with CPU policy in the optional plugin folder. Please only activate this plugin when you need to disable trace collecting when the agent process CPU usage is too high(over threshold). * Plugin for Spring 6.x and RestTemplate 6.x are in the optional plugin folder. Spring 6 requires Java 17 but SkyWalking is still compatible with Java 8. So, we put it in the optional plugin folder. * Plugin of nacos-client 2.x lib in optional plugin folder. The reason is many business irrelevant traces are generated, which cause extra payload to agents and backends, also spend more CPU, memory and network. * Plugin of netty-http 4.1.x lib in optional plugin folder. The reason is some frameworks use Netty HTTP as kernel, which could double the unnecessary spans and create incorrect RPC relative metrics. +### Notice due to Licence Restrictions +These plugins can't be provided in Apache release because of Oracle and Resin Licenses. +If you want to know details, please read [Apache license legal document](https://www.apache.org/legal/resolved.html) + +Due to license incompatibilities/restrictions these plugins are hosted and released in 3rd part repository, +go to [OpenSkywalking java plugin extension repository](https://github.com/OpenSkywalking/java-plugin-extensions) to get these. + ## Optional Level 3 Plugins. Expired Plugins These plugins are not tested in the CI/CD pipeline, as the previous added tests are not able to run according to the latest CI/CD infrastructure limitations, lack of maintenance, or dependencies/images not available(e.g. removed from DockerHub). diff --git a/docs/en/setup/service-agent/java-agent/agent-optional-plugins/Oracle-Resin-plugins.md b/docs/en/setup/service-agent/java-agent/agent-optional-plugins/Oracle-Resin-plugins.md deleted file mode 100644 index 145ef50133..0000000000 --- a/docs/en/setup/service-agent/java-agent/agent-optional-plugins/Oracle-Resin-plugins.md +++ /dev/null @@ -1,6 +0,0 @@ -## Oracle and Resin plugins -These plugins can't be provided in Apache release because of Oracle and Resin Licenses. -If you want to know details, please read [Apache license legal document](https://www.apache.org/legal/resolved.html) - -Due to license incompatibilities/restrictions these plugins are hosted and released in 3rd part repository, -go to [OpenSkywalking java plugin extension repository](https://github.com/OpenSkywalking/java-plugin-extensions) to get these. diff --git a/docs/en/setup/service-agent/java-agent/agent-optional-plugins/Spring-annotation-plugin.md b/docs/en/setup/service-agent/java-agent/agent-optional-plugins/Spring-annotation-plugin.md index 8f2336adee..ddf088ca11 100644 --- a/docs/en/setup/service-agent/java-agent/agent-optional-plugins/Spring-annotation-plugin.md +++ b/docs/en/setup/service-agent/java-agent/agent-optional-plugins/Spring-annotation-plugin.md @@ -1,4 +1,4 @@ -## Spring annotation plugin +# Spring annotation plugin This plugin allows to trace all methods of beans in Spring context, which are annotated with `@Bean`, `@Service`, `@Component` and `@Repository`. diff --git a/docs/en/setup/service-agent/java-agent/agent-optional-plugins/spring-gateway.md b/docs/en/setup/service-agent/java-agent/agent-optional-plugins/spring-gateway.md new file mode 100644 index 0000000000..6b84d91bec --- /dev/null +++ b/docs/en/setup/service-agent/java-agent/agent-optional-plugins/spring-gateway.md @@ -0,0 +1,96 @@ +# Spring Gateway Plugin + +Spring Gateway Plugin only support Spring Gateway 2.x, 3.x and 4.x. It has capabilities to create entry spans for +incoming calls, continue tracing context propagation in Spring Gateway and create exit spans for outgoing calls. + +About the filter extension of Gateway, it provides automatically support as much as possible, including GlobalFilter and GatewayFilter +support. However, the filter extension by using `chain.filter(exchange).then(...)` is not able to transparently. + +## Supported Auto-Instrument Filters + +```java +@Component +public class Filter1 implements GlobalFilter, Ordered { + + private static final Logger log = LoggerFactory.getLogger(Filter1.class); + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + // Available trace context + // For log framework integration(trace context log output) and manual trace context usage. + String traceId = TraceContext.traceId(); + log.info("available traceId: {}", traceId); + + String segmentId = TraceContext.segmentId(); + log.info("available segmentId: {}", segmentId); + + int spanId = TraceContext.spanId(); + log.info("available spanId: {}", spanId); + + return chain.filter(exchange); + } + @Override + public int getOrder() { + return -100; + } +} +``` +```java +@Component +public class GatewayFilter1 implements GatewayFilter { + + private static final Logger log = LoggerFactory.getLogger(GatewayFilter1.class); + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + // Available trace context + log.info("gatewayFilter1 running"); + return chain.filter(exchange); + } +} +``` + +## Unsupported Auto-Instrument Filters +Typically, in the following case, you need to read via [Webflux Tracing Assistant APIs](../Application-toolkit-webflux.md) to get the trace context. + +```java +@Component +public class UnsupportedFilter implements GlobalFilter, Ordered { + private static final Logger log = LoggerFactory.getLogger(UnsupportedFilter.class); + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + String traceId = TraceContext.traceId(); + // Trace ID is available as it's in the GlobalFilter. + log.info("available traceId: {}", traceId); + + String segmentId = TraceContext.segmentId(); + // Segment ID is available as it's in the GlobalFilter. + log.info("available segmentId: {}", segmentId); + + int spanId = TraceContext.spanId(); + // Span ID is available as it's in the GlobalFilter. + log.info("available spanId: {}", spanId); + + return chain.filter(exchange).then(Mono.fromRunnable(() -> { + // Trace ID/context is not available, N/A in the all following logs. + // The trace context is not available in the then-closure. + // Only webflux assistant API can get the trace context. + String traceId2 = WebFluxSkyWalkingTraceContext.traceId(exchange); + // Trace ID is not available, N/A in the logs. + log.info("unavailable in then-closure, available traceId: {} through webflux assistant API", traceId2); + + String segmentId2 = WebFluxSkyWalkingTraceContext.segmentId(exchange); + // Segment ID is not available, N/A in the logs. + log.info("unavailable in then-closure, available segmentId: {} through webflux assistant API", segmentId2); + + int spanId2 = WebFluxSkyWalkingTraceContext.spanId(exchange); + // Span ID is not available, N/A in the logs. + log.info("unavailable in then-closure, available spanId: {} through webflux assistant API", spanId2); + })); + } + + @Override + public int getOrder() { + return 10; + } +} + +``` \ No newline at end of file diff --git a/docs/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin.md b/docs/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin.md index dfaf2a1bed..cc42b54602 100644 --- a/docs/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin.md +++ b/docs/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin.md @@ -1,4 +1,4 @@ -## Support custom trace ignore +# Support Custom Trace Ignoring Here is an optional plugin `apm-trace-ignore-plugin` **Notice:** @@ -18,3 +18,5 @@ There are two ways to configure ignore patterns. Settings through system env has trace.ignore_path=/your/path/1/**,/your/path/2/** ``` +## Conflicts Notice +Due to the mechanism sharing, this plugin has conflicts with the plugin of **sampler plugin with CPU policy**(`trace-sampler-cpu-policy-plugin-*.jar`) in the optional plugin folder. \ No newline at end of file diff --git a/docs/menu.yml b/docs/menu.yml index 09729658a4..7ba331d586 100644 --- a/docs/menu.yml +++ b/docs/menu.yml @@ -81,7 +81,17 @@ catalog: - name: "Supported middleware, framework and library" path: "/en/setup/service-agent/java-agent/Supported-list" - name: "Optional Plugins" - path: "/en/setup/service-agent/java-agent/Optional-plugins" + catalog: + - name: "Plugin Manifest" + path: "/en/setup/service-agent/java-agent/Optional-plugins" + - name: "Spring Annotation Plugin" + path: "/en/setup/service-agent/java-agent/agent-optional-plugins/Spring-annotation-plugin" + - name: "Spring Gateway" + path: "/en/setup/service-agent/java-agent/agent-optional-plugins/spring-gateway" + - name: "Custom Trace Ignoring" + path: "/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin" + - name: "Kotlin Coroutine" + path: "/en/setup/service-agent/java-agent/agent-optional-plugins/Kotlin-Coroutine-plugin" - name: "Bootstrap/JVM class plugin" path: "/en/setup/service-agent/java-agent/Bootstrap-plugins" - name: "Agent Configuration Properties" From 1431cad9456bbb06a867aec0da9b2bed366ebba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Fri, 27 Dec 2024 09:42:34 +0800 Subject: [PATCH 048/114] Enhance gRPC server side async support. (#741) Change context and parent entry span propagation mechanism from gRPC ThreadLocal context to SkyWalking native dynamic field as new propagation mechanism, to better support async scenarios. --- CHANGES.md | 2 ++ .../grpc/v1/server/ServerInterceptor.java | 13 +++++----- .../grpc/v1/server/TracingServerCall.java | 26 ++++++++++++------- .../v1/server/TracingServerCallListener.java | 17 ++++++++---- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index edb63bbe9d..5e959990cd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,8 @@ Release Notes. * [doc] Add Spring Gateway Plugin document * [doc] Add 4 menu items guiding users to find important notices for Spring Annotation Plugin, Custom Trace Ignoring Plugin, Kotlin Coroutine Plugin, and Spring Gateway Plugin +* Change context and parent entry span propagation mechanism from gRPC ThreadLocal context to SkyWalking native dynamic + field as new propagation mechanism, to better support async scenarios. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java index f970d813f0..5db7248ea3 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java @@ -36,9 +36,6 @@ public class ServerInterceptor implements io.grpc.ServerInterceptor { - static final Context.Key CONTEXT_SNAPSHOT_KEY = Context.key("skywalking-grpc-context-snapshot"); - static final Context.Key ACTIVE_SPAN_KEY = Context.key("skywalking-grpc-active-span"); - @Override public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler handler) { @@ -59,15 +56,17 @@ public ServerCall.Listener interceptCall(ServerCall ContextSnapshot contextSnapshot = ContextManager.capture(); AbstractSpan asyncSpan = span.prepareForAsync(); - Context context = Context.current().withValues(CONTEXT_SNAPSHOT_KEY, contextSnapshot, ACTIVE_SPAN_KEY, asyncSpan); + //Context context = Context.current().withValues(CONTEXT_SNAPSHOT_KEY, contextSnapshot, ACTIVE_SPAN_KEY, asyncSpan); ServerCall.Listener listener = Contexts.interceptCall( - context, - new TracingServerCall<>(call), + Context.current(), + new TracingServerCall<>(call, contextSnapshot, asyncSpan), headers, (serverCall, metadata) -> new TracingServerCallListener<>( handler.startCall(serverCall, metadata), - serverCall.getMethodDescriptor() + serverCall.getMethodDescriptor(), + contextSnapshot, + asyncSpan ) ); ContextManager.stopSpan(asyncSpan); diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCall.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCall.java index 3361c4b7db..c674b5e16b 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCall.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCall.java @@ -18,38 +18,46 @@ package org.apache.skywalking.apm.plugin.grpc.v1.server; -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.RESPONSE_ON_CLOSE_OPERATION_NAME; -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.RESPONSE_ON_MESSAGE_OPERATION_NAME; -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.SERVER; - import io.grpc.ForwardingServerCall; import io.grpc.Metadata; import io.grpc.ServerCall; import io.grpc.Status; 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.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil; +import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.RESPONSE_ON_CLOSE_OPERATION_NAME; +import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.RESPONSE_ON_MESSAGE_OPERATION_NAME; +import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.SERVER; + public class TracingServerCall extends ForwardingServerCall.SimpleForwardingServerCall { private final String operationPrefix; + private final ContextSnapshot contextSnapshot; + private final AbstractSpan parentEntrySpan; - protected TracingServerCall(ServerCall delegate) { + protected TracingServerCall(ServerCall delegate, + final ContextSnapshot contextSnapshot, + final AbstractSpan parentEntrySpan) { super(delegate); this.operationPrefix = OperationNameFormatUtil.formatOperationName(delegate.getMethodDescriptor()) + SERVER; + this.contextSnapshot = contextSnapshot; + this.parentEntrySpan = parentEntrySpan; } @Override public void sendMessage(RESPONSE message) { // We just create the request on message span for server stream calls. if (!getMethodDescriptor().getType().serverSendsOneMessage()) { - final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + RESPONSE_ON_MESSAGE_OPERATION_NAME); + final AbstractSpan span = ContextManager.createLocalSpan( + operationPrefix + RESPONSE_ON_MESSAGE_OPERATION_NAME); span.setComponent(ComponentsDefine.GRPC); span.setLayer(SpanLayer.RPC_FRAMEWORK); - ContextManager.continued(ServerInterceptor.CONTEXT_SNAPSHOT_KEY.get()); + ContextManager.continued(contextSnapshot); try { super.sendMessage(message); } catch (Throwable t) { @@ -68,7 +76,7 @@ public void close(Status status, Metadata trailers) { final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + RESPONSE_ON_CLOSE_OPERATION_NAME); span.setComponent(ComponentsDefine.GRPC); span.setLayer(SpanLayer.RPC_FRAMEWORK); - ContextManager.continued(ServerInterceptor.CONTEXT_SNAPSHOT_KEY.get()); + ContextManager.continued(contextSnapshot); switch (status.getCode()) { case OK: break; @@ -94,7 +102,7 @@ public void close(Status status, Metadata trailers) { break; } Tags.RPC_RESPONSE_STATUS_CODE.set(span, status.getCode().name()); - ServerInterceptor.ACTIVE_SPAN_KEY.get().asyncFinish(); + parentEntrySpan.asyncFinish(); try { super.close(status, trailers); diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCallListener.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCallListener.java index cb19e86c6c..65910f003f 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCallListener.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCallListener.java @@ -22,6 +22,7 @@ import io.grpc.MethodDescriptor; import io.grpc.ServerCall; 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.context.trace.SpanLayer; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; @@ -34,11 +35,17 @@ public class TracingServerCallListener extends ForwardingServerCallListener.SimpleForwardingServerCallListener { private final MethodDescriptor.MethodType methodType; private final String operationPrefix; + private final ContextSnapshot contextSnapshot; + private final AbstractSpan parentEntrySpan; - protected TracingServerCallListener(ServerCall.Listener delegate, MethodDescriptor descriptor) { + protected TracingServerCallListener(ServerCall.Listener delegate, MethodDescriptor descriptor, + final ContextSnapshot contextSnapshot, + final AbstractSpan parentEntrySpan) { super(delegate); this.methodType = descriptor.getType(); this.operationPrefix = OperationNameFormatUtil.formatOperationName(descriptor) + SERVER; + this.contextSnapshot = contextSnapshot; + this.parentEntrySpan = parentEntrySpan; } @Override @@ -48,7 +55,7 @@ public void onMessage(REQUEST message) { final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + REQUEST_ON_MESSAGE_OPERATION_NAME); span.setComponent(ComponentsDefine.GRPC); span.setLayer(SpanLayer.RPC_FRAMEWORK); - ContextManager.continued(ServerInterceptor.CONTEXT_SNAPSHOT_KEY.get()); + ContextManager.continued(contextSnapshot); try { super.onMessage(message); } catch (Throwable t) { @@ -67,7 +74,7 @@ public void onCancel() { final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + REQUEST_ON_CANCEL_OPERATION_NAME); span.setComponent(ComponentsDefine.GRPC); span.setLayer(SpanLayer.RPC_FRAMEWORK); - ContextManager.continued(ServerInterceptor.CONTEXT_SNAPSHOT_KEY.get()); + ContextManager.continued(contextSnapshot); try { super.onCancel(); } catch (Throwable t) { @@ -75,7 +82,7 @@ public void onCancel() { throw t; } finally { ContextManager.stopSpan(); - ServerInterceptor.ACTIVE_SPAN_KEY.get().asyncFinish(); + parentEntrySpan.asyncFinish(); } } @@ -84,7 +91,7 @@ public void onHalfClose() { final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + REQUEST_ON_HALF_CLOSE_OPERATION_NAME); span.setComponent(ComponentsDefine.GRPC); span.setLayer(SpanLayer.RPC_FRAMEWORK); - ContextManager.continued(ServerInterceptor.CONTEXT_SNAPSHOT_KEY.get()); + ContextManager.continued(contextSnapshot); try { super.onHalfClose(); } catch (Throwable t) { From b0d5bc16f4f8d9752988eeb91b5539c2268ed3e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Fri, 27 Dec 2024 12:10:55 +0800 Subject: [PATCH 049/114] Polish (#742) --- .../skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java index 5db7248ea3..b285ff169d 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java @@ -56,8 +56,6 @@ public ServerCall.Listener interceptCall(ServerCall ContextSnapshot contextSnapshot = ContextManager.capture(); AbstractSpan asyncSpan = span.prepareForAsync(); - //Context context = Context.current().withValues(CONTEXT_SNAPSHOT_KEY, contextSnapshot, ACTIVE_SPAN_KEY, asyncSpan); - ServerCall.Listener listener = Contexts.interceptCall( Context.current(), new TracingServerCall<>(call, contextSnapshot, asyncSpan), From d53f04b7bfd534e8611312711a0885988ffca4fa Mon Sep 17 00:00:00 2001 From: Zixin Zhou Date: Sun, 29 Dec 2024 08:16:05 +0800 Subject: [PATCH 050/114] Add Caffeine plugin as optional (#743) --- .github/workflows/ci.yaml | 2 +- .github/workflows/codeql.yaml | 4 +- .github/workflows/plugins-jdk17-test.1.yaml | 1 + CHANGES.md | 1 + .../trace/component/ComponentsDefine.java | 1 + apm-sniffer/config/agent.config | 4 + .../caffeine-3.x-plugin/pom.xml | 46 +++++ .../v3/AbstractCaffeineInterceptor.java | 71 ++++++++ .../v3/CaffeineIterableInterceptor.java | 46 +++++ .../caffeine/v3/CaffeineMapInterceptor.java | 45 +++++ .../v3/CaffeineOperationTransform.java | 34 ++++ .../caffeine/v3/CaffeinePluginConfig.java | 50 ++++++ .../v3/CaffeineStringInterceptor.java | 40 +++++ .../v3/define/CaffeineInstrumentation.java | 119 +++++++++++++ .../src/main/resources/skywalking-plugin.def | 17 ++ .../caffeine/v3/CaffeineInterceptorTest.java | 149 ++++++++++++++++ .../org.mockito.plugins.MockMaker | 1 + apm-sniffer/optional-plugins/pom.xml | 1 + .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 3 +- .../java-agent/configurations.md | 23 +-- .../caffeine-3.x-scenario/bin/startup.sh | 21 +++ .../config/expectedData.yaml | 163 ++++++++++++++++++ .../caffeine-3.x-scenario/configuration.yml | 22 +++ .../scenarios/caffeine-3.x-scenario/pom.xml | 111 ++++++++++++ .../src/main/assembly/assembly.xml | 41 +++++ .../apm/testcase/caffeine/Application.java | 30 ++++ .../controller/CaffeineController.java | 56 ++++++ .../controller/HeartbeatController.java | 31 ++++ .../src/main/resources/application.yaml | 21 +++ .../support-version.list | 18 ++ 31 files changed, 1158 insertions(+), 15 deletions(-) create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/AbstractCaffeineInterceptor.java create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineIterableInterceptor.java create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineMapInterceptor.java create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineOperationTransform.java create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeinePluginConfig.java create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineStringInterceptor.java create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/define/CaffeineInstrumentation.java create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineInterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker create mode 100755 test/plugin/scenarios/caffeine-3.x-scenario/bin/startup.sh create mode 100755 test/plugin/scenarios/caffeine-3.x-scenario/config/expectedData.yaml create mode 100755 test/plugin/scenarios/caffeine-3.x-scenario/configuration.yml create mode 100755 test/plugin/scenarios/caffeine-3.x-scenario/pom.xml create mode 100755 test/plugin/scenarios/caffeine-3.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/Application.java create mode 100644 test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/controller/CaffeineController.java create mode 100644 test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/controller/HeartbeatController.java create mode 100755 test/plugin/scenarios/caffeine-3.x-scenario/src/main/resources/application.yaml create mode 100755 test/plugin/scenarios/caffeine-3.x-scenario/support-version.list diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 20e2bae6d2..e2078dd4ab 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -42,7 +42,7 @@ jobs: build: name: Java ${{ matrix.java-version }} / ${{ matrix.os }} runs-on: ${{ matrix.os }}-latest - timeout-minutes: 60 + timeout-minutes: 90 needs: [ license ] strategy: fail-fast: true diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 0932d63cee..1abc057ad0 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -54,11 +54,11 @@ jobs: java-version: 17 - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} - run: ./mvnw -q -Dmaven.test.skip=true clean install || ./mvnw -q -Dmaven.test.skip=true clean install - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index 949e69cfa1..80ff29bb67 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -63,6 +63,7 @@ jobs: - c3p0-0.9.0.x-0.9.1.x-scenario - c3p0-0.9.2.x-0.10.x-scenario - spring-scheduled-6.x-scenario + - caffeine-3.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 5e959990cd..8a74479321 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -25,6 +25,7 @@ Release Notes. Plugin, Kotlin Coroutine Plugin, and Spring Gateway Plugin * Change context and parent entry span propagation mechanism from gRPC ThreadLocal context to SkyWalking native dynamic field as new propagation mechanism, to better support async scenarios. +* Add Caffeine plugin as optional. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index 101abcdb5e..e10b207ce5 100755 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -259,4 +259,5 @@ public class ComponentsDefine { public static final OfficialComponent SOLON_MVC = new OfficialComponent(158, "SolonMVC"); + public static final OfficialComponent CAFFEINE = new OfficialComponent(160, "Caffeine"); } diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index 695e47349f..f27572a1e0 100755 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -332,3 +332,7 @@ plugin.solon.http_params_length_threshold=${SW_PLUGIN_SOLON_HTTP_PARAMS_LENGTH_T plugin.solon.include_http_headers=${SW_PLUGIN_SOLON_INCLUDE_HTTP_HEADERS:} # Define the max length of collected HTTP body. The default value(=0) means not collecting. plugin.solon.http_body_length_threshold=${SW_PLUGIN_SOLON_HTTP_BODY_LENGTH_THRESHOLD:0} +# Specify which command should be converted to write operation +plugin.caffeine.operation_mapping_write=${SW_PLUGIN_CAFFEINE_OPERATION_MAPPING_WRITE:put,putAll,remove,clear} +# Specify which command should be converted to read operation +plugin.caffeine.operation_mapping_read=${SW_PLUGIN_CAFFEINE_OPERATION_MAPPING_READ:getIfPresent,getAllPresent,computeIfAbsent} diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml new file mode 100644 index 0000000000..3170ed81a2 --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml @@ -0,0 +1,46 @@ + + + + + 4.0.0 + + org.apache.skywalking + optional-plugins + 9.4.0-SNAPSHOT + + + apm-caffeine-3.x-plugin + jar + caffeine-3.x-plugin + + + UTF-8 + 3.1.8 + + + + + com.github.ben-manes.caffeine + caffeine + ${caffeine.version} + provided + + + diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/AbstractCaffeineInterceptor.java b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/AbstractCaffeineInterceptor.java new file mode 100644 index 0000000000..9c66cabd08 --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/AbstractCaffeineInterceptor.java @@ -0,0 +1,71 @@ +/* + * 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.caffeine.v3; + +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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 static org.apache.skywalking.apm.plugin.caffeine.v3.CaffeineOperationTransform.transformOperation; + +abstract public class AbstractCaffeineInterceptor implements InstanceMethodsAroundInterceptor { + + protected AbstractSpan generateSpanInfo(String methodName) { + AbstractSpan span = ContextManager.createLocalSpan("Caffeine/" + methodName); + span.setComponent(ComponentsDefine.CAFFEINE); + Tags.CACHE_TYPE.set(span, ComponentsDefine.CAFFEINE.getName()); + Tags.CACHE_CMD.set(span, methodName); + transformOperation(methodName).ifPresent(op -> Tags.CACHE_OP.set(span, op)); + SpanLayer.asCache(span); + return span; + } + + @Override + public void beforeMethod(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] argumentsTypes, + final MethodInterceptResult result) throws Throwable { + } + + @Override + public Object afterMethod(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] argumentsTypes, + final Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] argumentsTypes, + final Throwable t) { + ContextManager.activeSpan().log(t); + } +} diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineIterableInterceptor.java b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineIterableInterceptor.java new file mode 100644 index 0000000000..ef5860e46f --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineIterableInterceptor.java @@ -0,0 +1,46 @@ +/* + * 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.caffeine.v3; + +import java.lang.reflect.Method; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +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.MethodInterceptResult; + +public class CaffeineIterableInterceptor extends AbstractCaffeineInterceptor { + + @Override + public void beforeMethod(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] argumentsTypes, + final MethodInterceptResult result) throws Throwable { + AbstractSpan span = generateSpanInfo(method.getName()); + if (allArguments != null && allArguments.length > 0) { + String keys = StreamSupport + .stream(((Iterable) allArguments[0]).spliterator(), false) + .map(String::valueOf) + .collect(Collectors.joining(",")); + Tags.CACHE_KEY.set(span, keys); + } + } +} diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineMapInterceptor.java b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineMapInterceptor.java new file mode 100644 index 0000000000..98258bbb38 --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineMapInterceptor.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.caffeine.v3; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +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.MethodInterceptResult; + +public class CaffeineMapInterceptor extends AbstractCaffeineInterceptor { + + @Override + public void beforeMethod(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] argumentsTypes, + final MethodInterceptResult result) throws Throwable { + AbstractSpan span = generateSpanInfo(method.getName()); + if (allArguments != null && allArguments.length > 0) { + String keys = ((Map) allArguments[0]) + .keySet().stream().map(String::valueOf) + .collect(Collectors.joining(",")); + Tags.CACHE_KEY.set(span, keys); + } + } +} diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineOperationTransform.java b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineOperationTransform.java new file mode 100644 index 0000000000..0f4a128a92 --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineOperationTransform.java @@ -0,0 +1,34 @@ +/* + * 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.caffeine.v3; + +import java.util.Optional; + +public class CaffeineOperationTransform { + + public static Optional transformOperation(String cmd) { + if (CaffeinePluginConfig.Plugin.Caffeine.OPERATION_MAPPING_READ.contains(cmd)) { + return Optional.of("read"); + } + if (CaffeinePluginConfig.Plugin.Caffeine.OPERATION_MAPPING_WRITE.contains(cmd)) { + return Optional.of("write"); + } + return Optional.empty(); + } +} diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeinePluginConfig.java b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeinePluginConfig.java new file mode 100644 index 0000000000..f775668bee --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeinePluginConfig.java @@ -0,0 +1,50 @@ +/* + * 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.caffeine.v3; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import org.apache.skywalking.apm.agent.core.boot.PluginConfig; + +/** + * Operation represent a cache span is "write" or "read" action , and "op"(operation) is tagged with key "cache.op" + * usually This config term define which command should be converted to write Operation . + * + * @see org.apache.skywalking.apm.agent.core.context.tag.Tags#CACHE_OP + * @see CaffeineOperationTransform#transformOperation(String) + */ +public class CaffeinePluginConfig { + public static class Plugin { + @PluginConfig(root = CaffeinePluginConfig.class) + public static class Caffeine { + public static Set OPERATION_MAPPING_WRITE = new HashSet<>(Arrays.asList( + "put", + "putAll", + "remove", + "clear" + )); + public static Set OPERATION_MAPPING_READ = new HashSet<>(Arrays.asList( + "getIfPresent", + "getAllPresent", + "computeIfAbsent" + )); + } + } +} \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineStringInterceptor.java b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineStringInterceptor.java new file mode 100644 index 0000000000..82b34ca48d --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineStringInterceptor.java @@ -0,0 +1,40 @@ +/* + * 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.caffeine.v3; + +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +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.MethodInterceptResult; + +public class CaffeineStringInterceptor extends AbstractCaffeineInterceptor { + + @Override + public void beforeMethod(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] argumentsTypes, + final MethodInterceptResult result) throws Throwable { + AbstractSpan span = generateSpanInfo(method.getName()); + if (allArguments != null && allArguments.length > 0 && allArguments[0] instanceof String) { + Tags.CACHE_KEY.set(span, allArguments[0].toString()); + } + } +} diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/define/CaffeineInstrumentation.java b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/define/CaffeineInstrumentation.java new file mode 100644 index 0000000000..50e5b3751a --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/caffeine/v3/define/CaffeineInstrumentation.java @@ -0,0 +1,119 @@ +/* + * 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.caffeine.v3.define; + +import java.util.Map; +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.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch.byMultiClassMatch; + +public class CaffeineInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + public static final String BOUNDED_LOCAL_INTERCEPT_CLASS = "com.github.benmanes.caffeine.cache.BoundedLocalCache"; + public static final String UNBOUNDED_LOCAL_INTERCEPT_CLASS = "com.github.benmanes.caffeine.cache.UnboundedLocalCache"; + public static final String CAFFEINE_ITERABLE_ENHANCE_CLASS = "org.apache.skywalking.apm.plugin.caffeine.v3.CaffeineIterableInterceptor"; + public static final String CAFFEINE_MAP_ENHANCE_CLASS = "org.apache.skywalking.apm.plugin.caffeine.v3.CaffeineMapInterceptor"; + public static final String CAFFEINE_STRING_ENHANCE_CLASS = "org.apache.skywalking.apm.plugin.caffeine.v3.CaffeineStringInterceptor"; + + // read/write operations + public static final String GET_IF_PRESENT_METHOD = "getIfPresent"; + public static final String GET_ALL_PRESENT_METHOD = "getAllPresent"; + public static final String COMPUTE_IF_ABSENT_METHOD = "computeIfAbsent"; + public static final String PUT_METHOD = "put"; + public static final String PUT_ALL_METHOD = "putAll"; + public static final String REMOVE_METHOD = "remove"; + public static final String CLEAR_METHOD = "clear"; + + @Override + protected ClassMatch enhanceClass() { + return byMultiClassMatch(BOUNDED_LOCAL_INTERCEPT_CLASS, UNBOUNDED_LOCAL_INTERCEPT_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(GET_IF_PRESENT_METHOD) + .and(takesArguments(2)) + .or(named(COMPUTE_IF_ABSENT_METHOD).and(takesArguments(4))) + .or(named(PUT_METHOD).and(takesArguments(2))) + .or(named(REMOVE_METHOD).and(takesArguments(1))) + .or(named(CLEAR_METHOD).and(takesArguments(0))); + } + + @Override + public String getMethodsInterceptor() { + return CAFFEINE_STRING_ENHANCE_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(GET_ALL_PRESENT_METHOD).and(takesArgument(0, Iterable.class)); + } + + @Override + public String getMethodsInterceptor() { + return CAFFEINE_ITERABLE_ENHANCE_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(PUT_ALL_METHOD).and(takesArgument(0, Map.class)); + } + + @Override + public String getMethodsInterceptor() { + return CAFFEINE_MAP_ENHANCE_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..1edf1e3a0e --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-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. + +caffeine-3.x=org.apache.skywalking.apm.plugin.caffeine.v3.define.CaffeineInstrumentation diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineInterceptorTest.java b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineInterceptorTest.java new file mode 100644 index 0000000000..7642ae110d --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/caffeine/v3/CaffeineInterceptorTest.java @@ -0,0 +1,149 @@ +/* + * 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.caffeine.v3; + +import com.github.benmanes.caffeine.cache.Expiry; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import static org.hamcrest.CoreMatchers.is; + +@RunWith(TracingSegmentRunner.class) +public class CaffeineInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + private CaffeineIterableInterceptor caffeineIterableInterceptor; + private CaffeineMapInterceptor caffeineMapInterceptor; + private CaffeineStringInterceptor caffeineStringInterceptor; + private Object[] operateObjectArguments; + + private Exception exception; + + private Method getAllPresentMethod; + private Method getIfPresentMethod; + private Method computeIfAbsentMethod; + + private Method putMethod; + private Method putAllMethod; + private Method removeMethod; + private Method cleanMethod; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @Before + public void setUp() throws Exception { + caffeineIterableInterceptor = new CaffeineIterableInterceptor(); + caffeineMapInterceptor = new CaffeineMapInterceptor(); + caffeineStringInterceptor = new CaffeineStringInterceptor(); + exception = new Exception(); + operateObjectArguments = new Object[] {"dataKey"}; + Class cache = Class.forName("com.github.benmanes.caffeine.cache.BoundedLocalCache"); + getAllPresentMethod = cache.getDeclaredMethod("getAllPresent", Iterable.class); + getIfPresentMethod = cache.getDeclaredMethod("getIfPresent", Object.class, boolean.class); + computeIfAbsentMethod = cache.getDeclaredMethod( + "computeIfAbsent", Object.class, Function.class, boolean.class, boolean.class); + putMethod = cache.getDeclaredMethod("put", Object.class, Object.class, Expiry.class, boolean.class); + putAllMethod = cache.getDeclaredMethod("putAll", Map.class); + removeMethod = cache.getDeclaredMethod("remove", Object.class); + cleanMethod = cache.getDeclaredMethod("clear"); + } + + @Test + public void testGetAllPresentSuccess() throws Throwable { + caffeineIterableInterceptor.beforeMethod(null, getAllPresentMethod, null, null, null); + caffeineIterableInterceptor.handleMethodException(null, getAllPresentMethod, null, null, exception); + caffeineIterableInterceptor.afterMethod(null, getAllPresentMethod, null, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void testGetIfPresentSuccess() throws Throwable { + caffeineStringInterceptor.beforeMethod(null, getIfPresentMethod, operateObjectArguments, null, null); + caffeineStringInterceptor.handleMethodException( + null, getIfPresentMethod, operateObjectArguments, null, exception); + caffeineStringInterceptor.afterMethod(null, getIfPresentMethod, operateObjectArguments, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void testComputeIfAbsentMethodSuccess() throws Throwable { + caffeineStringInterceptor.beforeMethod(null, computeIfAbsentMethod, null, null, null); + caffeineStringInterceptor.handleMethodException(null, computeIfAbsentMethod, null, null, exception); + caffeineStringInterceptor.afterMethod(null, computeIfAbsentMethod, null, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void testPutMethodSuccess() throws Throwable { + caffeineStringInterceptor.beforeMethod(null, putMethod, operateObjectArguments, null, null); + caffeineStringInterceptor.handleMethodException(null, putMethod, operateObjectArguments, null, exception); + caffeineStringInterceptor.afterMethod(null, putMethod, operateObjectArguments, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void testPutAllMethodSuccess() throws Throwable { + caffeineMapInterceptor.beforeMethod(null, putAllMethod, null, null, null); + caffeineMapInterceptor.handleMethodException(null, putAllMethod, null, null, exception); + caffeineMapInterceptor.afterMethod(null, putAllMethod, null, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void testRemoveMethodSuccess() throws Throwable { + caffeineStringInterceptor.beforeMethod(null, removeMethod, operateObjectArguments, null, null); + caffeineStringInterceptor.handleMethodException(null, removeMethod, operateObjectArguments, null, exception); + caffeineStringInterceptor.afterMethod(null, removeMethod, operateObjectArguments, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void testClearMethodSuccess() throws Throwable { + caffeineStringInterceptor.beforeMethod(null, cleanMethod, null, null, null); + caffeineStringInterceptor.handleMethodException(null, cleanMethod, null, null, exception); + caffeineStringInterceptor.afterMethod(null, cleanMethod, null, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } +} diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..1f0955d450 --- /dev/null +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml index 4a55525da8..6369484e82 100644 --- a/apm-sniffer/optional-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/pom.xml @@ -59,6 +59,7 @@ trace-sampler-cpu-policy-plugin nacos-client-2.x-plugin netty-http-4.1.x-plugin + caffeine-3.x-plugin 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 2c7b51a6c3..847a81dbec 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -179,3 +179,4 @@ - activemq-artemis-jakarta-client-2.x - c3p0-0.9.x - solon-2.x +- caffeine-3.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index fe3bcd231d..cd51b8d2ce 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -139,8 +139,9 @@ metrics based on the tracing data. * JRE Callable and Runnable (Optional²) * JRE ForkJoinPool (Optional²) * Cache - * [Ehcache](https://www.ehcache.org/) 2.x + * [Ehcache](https://www.ehcache.org/) 2.x (Optional²) * [GuavaCache](https://github.com/google/guava) 18.x -> 23.x (Optional²) + * [Caffeine](https://github.com/ben-manes/caffeine) 3.x (Optional²) * Kotlin * [Coroutine](https://kotlinlang.org/docs/coroutines-overview.html) 1.0.1 -> 1.3.x (Optional²) * GraphQL diff --git a/docs/en/setup/service-agent/java-agent/configurations.md b/docs/en/setup/service-agent/java-agent/configurations.md index 83837d33b7..9c6cc2d7f6 100644 --- a/docs/en/setup/service-agent/java-agent/configurations.md +++ b/docs/en/setup/service-agent/java-agent/configurations.md @@ -126,17 +126,18 @@ This is the properties list supported in `agent/config/agent.config`. | `plugin.memcached.operation_mapping_read` | Specify which command should be converted to `read` operation | SW_PLUGIN_MEMCACHED_OPERATION_MAPPING_READ | `set,add,replace,append,prepend,cas,delete,touch,incr,decr` | | `plugin.ehcache.operation_mapping_write` | Specify which command should be converted to `write` operation | SW_PLUGIN_EHCACHE_OPERATION_MAPPING_WRITE | `get,getAll,getQuiet,getKeys,getKeysWithExpiryCheck,getKeysNoDuplicateCheck,releaseRead,tryRead,getWithLoader,getAll,loadAll,getAllWithLoader` | | `plugin.ehcache.operation_mapping_read` | Specify which command should be converted to `read` operation | SW_PLUGIN_EHCACHE_OPERATION_MAPPING_READ | `tryRemoveImmediately,remove,removeAndReturnElement,removeAll,removeQuiet,removeWithWriter,put,putAll,replace,removeQuiet,removeWithWriter,removeElement,removeAll,putWithWriter,putQuiet,putIfAbsent,putIfAbsent` | -| `plugin.guavacache.operation_mapping_write` | Specify which command should be converted to `write` operation | SW_PLUGIN_GUAVACACHE_OPERATION_MAPPING_WRITE | `getIfPresent,get,getAllPresent,size` | -| `plugin.guavacache.operation_mapping_read` | Specify which command should be converted to `read` operation | SW_PLUGIN_GUAVACACHE_OPERATION_MAPPING_READ | `put,putAll,invalidate,invalidateAll,invalidateAll,cleanUp` -| `plugin.nettyhttp.collect_request_body` | This config item controls that whether the Netty-http plugin should collect the http body of the request. | SW_PLUGIN_NETTY_HTTP_COLLECT_REQUEST_BODY | `false` | -| `plugin.nettyhttp.filter_length_limit` | When `COLLECT_REQUEST_BODY` is enabled, how many characters to keep and send to the OAP backend, use negative values to keep and send the complete body. | SW_PLUGIN_NETTY_HTTP_FILTER_LENGTH_LIMIT | `1024` | -| `plugin.nettyhttp.supported_content_types_prefix` | When `COLLECT_REQUEST_BODY` is enabled and content-type start with `HTTP_SUPPORTED_CONTENT_TYPES_PREFIX`, collect the body of the request , multiple paths should be separated by `,` | SW_PLUGIN_NETTY_HTTP_SUPPORTED_CONTENT_TYPES_PREFIX | `application/json,text/` | -| `plugin.rocketmqclient.collect_message_keys` | If set to true, the keys of messages would be collected by the plugin for RocketMQ Java client. -| `plugin.rocketmqclient.collect_message_tags` | If set to true, the tags of messages would be collected by the plugin for RocketMQ Java client. -| `plugin.solon.http_params_length_threshold` | Define the max length of collected HTTP parameters. The default value(=0) means not collecting. | SW_PLUGIN_SOLON_HTTP_PARAMS_LENGTH_THRESHOLD | `0` | -| `plugin.solon.include_http_headers` | It controls what header data should be collected, values must be in lower case, if empty, no header data will be collected. default is empty. | SW_PLUGIN_SOLON_INCLUDE_HTTP_HEADERS | ``(No header would be collected) | -| `plugin.solon.http_body_length_threshold` | Define the max length of collected HTTP body. The default value(=0) means not collecting. | SW_PLUGIN_SOLON_HTTP_BODY_LENGTH_THRESHOLD | `0` | - +| `plugin.guavacache.operation_mapping_write` | Specify which command should be converted to `write` operation | SW_PLUGIN_GUAVACACHE_OPERATION_MAPPING_WRITE | `put,putAll,invalidate,invalidateAll,invalidateAll,cleanUp` | +| `plugin.guavacache.operation_mapping_read` | Specify which command should be converted to `read` operation | SW_PLUGIN_GUAVACACHE_OPERATION_MAPPING_READ | `getIfPresent,get,getAllPresent,size` | +| `plugin.nettyhttp.collect_request_body` | This config item controls that whether the Netty-http plugin should collect the http body of the request. | SW_PLUGIN_NETTY_HTTP_COLLECT_REQUEST_BODY | `false` | +| `plugin.nettyhttp.filter_length_limit` | When `COLLECT_REQUEST_BODY` is enabled, how many characters to keep and send to the OAP backend, use negative values to keep and send the complete body. | SW_PLUGIN_NETTY_HTTP_FILTER_LENGTH_LIMIT | `1024` | +| `plugin.nettyhttp.supported_content_types_prefix` | When `COLLECT_REQUEST_BODY` is enabled and content-type start with `HTTP_SUPPORTED_CONTENT_TYPES_PREFIX`, collect the body of the request , multiple paths should be separated by `,` | SW_PLUGIN_NETTY_HTTP_SUPPORTED_CONTENT_TYPES_PREFIX | `application/json,text/` | +| `plugin.rocketmqclient.collect_message_keys` | If set to true, the keys of messages would be collected by the plugin for RocketMQ Java client. | | | +| `plugin.rocketmqclient.collect_message_tags` | If set to true, the tags of messages would be collected by the plugin for RocketMQ Java client. | | | +| `plugin.solon.http_params_length_threshold` | Define the max length of collected HTTP parameters. The default value(=0) means not collecting. | SW_PLUGIN_SOLON_HTTP_PARAMS_LENGTH_THRESHOLD | `0` | +| `plugin.solon.include_http_headers` | It controls what header data should be collected, values must be in lower case, if empty, no header data will be collected. default is empty. | SW_PLUGIN_SOLON_INCLUDE_HTTP_HEADERS | ``(No header would be collected) | +| `plugin.solon.http_body_length_threshold` | Define the max length of collected HTTP body. The default value(=0) means not collecting. | SW_PLUGIN_SOLON_HTTP_BODY_LENGTH_THRESHOLD | `0` | +| `plugin.caffeine.operation_mapping_write` | Specify which command should be converted to `write` operation | SW_PLUGIN_EHCACHE_OPERATION_MAPPING_WRITE | `put,putAll,remove,clear` | +| `plugin.caffeine.operation_mapping_read` | Specify which command should be converted to `read` operation | SW_PLUGIN_EHCACHE_OPERATION_MAPPING_READ | `getIfPresent,getAllPresent,computeIfAbsent` | # Reset Collection/Map type configurations as empty collection. diff --git a/test/plugin/scenarios/caffeine-3.x-scenario/bin/startup.sh b/test/plugin/scenarios/caffeine-3.x-scenario/bin/startup.sh new file mode 100755 index 0000000000..01883d186d --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-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/caffeine-3.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/caffeine-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/caffeine-3.x-scenario/config/expectedData.yaml new file mode 100755 index 0000000000..133ede4755 --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-scenario/config/expectedData.yaml @@ -0,0 +1,163 @@ +# 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: caffeine-3.x-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: Caffeine/put + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 160 + isError: false + spanType: Local + peer: '' + tags: + - { key: cache.type, value: Caffeine } + - { key: cache.cmd, value: put } + - { key: cache.op, value: write } + - { key: cache.key, value: "1" } + skipAnalysis: 'false' + - operationName: Caffeine/putAll + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 160 + isError: false + spanType: Local + peer: '' + tags: + - { key: cache.type, value: Caffeine } + - { key: cache.cmd, value: putAll } + - { key: cache.op, value: write } + - { key: cache.key, value: "2" } + skipAnalysis: 'false' + - operationName: Caffeine/computeIfAbsent + parentSpanId: 0 + spanId: 3 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 160 + isError: false + spanType: Local + peer: '' + tags: + - { key: cache.type, value: Caffeine } + - { key: cache.cmd, value: computeIfAbsent } + - { key: cache.op, value: read } + - { key: cache.key, value: "1" } + - operationName: Caffeine/getIfPresent + parentSpanId: 0 + spanId: 4 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 160 + isError: false + spanType: Local + peer: '' + tags: + - { key: cache.type, value: Caffeine } + - { key: cache.cmd, value: getIfPresent } + - { key: cache.op, value: read } + - { key: cache.key, value: "1" } + skipAnalysis: 'false' + - operationName: Caffeine/getAllPresent + parentSpanId: 0 + spanId: 5 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 160 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + tags: + - { key: cache.type, value: Caffeine } + - { key: cache.cmd, value: getAllPresent } + - { key: cache.op, value: read } + - { key: cache.key, value: '2' } + - operationName: Caffeine/remove + parentSpanId: 0 + spanId: 6 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 160 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + tags: + - { key: cache.type, value: Caffeine } + - { key: cache.cmd, value: remove } + - { key: cache.op, value: write } + - { key: cache.key, value: '1' } + - operationName: Caffeine/remove + parentSpanId: 0 + spanId: 7 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 160 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + tags: + - { key: cache.type, value: Caffeine } + - { key: cache.cmd, value: remove } + - { key: cache.op, value: write } + - { key: cache.key, value: '2' } + - operationName: Caffeine/clear + parentSpanId: 0 + spanId: 8 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 160 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + tags: + - { key: cache.type, value: Caffeine } + - { key: cache.cmd, value: clear } + - { key: cache.op, value: write } + - operationName: GET:/caffeine-3.x-scenario/case/caffeine + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + tags: + - { key: url, value: 'http://localhost:8080/caffeine-3.x-scenario/case/caffeine' } + - { key: http.method, value: GET } + - { key: http.status_code, value: '200' } + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/caffeine-3.x-scenario/configuration.yml b/test/plugin/scenarios/caffeine-3.x-scenario/configuration.yml new file mode 100755 index 0000000000..00208eefa9 --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-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/caffeine-3.x-scenario/case/caffeine +healthCheck: http://localhost:8080/caffeine-3.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +runningMode: with_optional +withPlugins: apm-caffeine-3.x-plugin-*.jar \ No newline at end of file diff --git a/test/plugin/scenarios/caffeine-3.x-scenario/pom.xml b/test/plugin/scenarios/caffeine-3.x-scenario/pom.xml new file mode 100755 index 0000000000..a627109082 --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-scenario/pom.xml @@ -0,0 +1,111 @@ + + + + + org.apache.skywalking.apm.testcase + caffeine-3.x-scenario + 1.0.0 + jar + + 4.0.0 + + + 17 + UTF-8 + 3.8.1 + 6.0.2 + ${test.framework.version} + 3.0.0 + 3.1.8 + + + skywalking-caffeine-3.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + com.github.ben-manes.caffeine + caffeine + ${caffeine.version} + + + + + caffeine-3.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${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/caffeine-3.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/assembly/assembly.xml new file mode 100755 index 0000000000..382a68db61 --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/caffeine-3.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/Application.java b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/Application.java new file mode 100644 index 0000000000..a4739cfbfe --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/Application.java @@ -0,0 +1,30 @@ +/* + * 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.testcase.caffeine; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/controller/CaffeineController.java b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/controller/CaffeineController.java new file mode 100644 index 0000000000..f8bad1d288 --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/controller/CaffeineController.java @@ -0,0 +1,56 @@ +/* + * 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.testcase.caffeine.controller; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import java.util.HashMap; +import java.util.Map; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class CaffeineController { + + Cache caffeine = Caffeine.newBuilder().build(); + + @GetMapping("/case/caffeine") + public void testCase() { + try { + Map data = new HashMap<>(); + data.put("2", "value-2"); + + // put operations + caffeine.put("1", "value-1"); + caffeine.putAll(data); + + // get operations + caffeine.get("1", o -> "default"); + caffeine.getIfPresent("1"); + caffeine.getAllPresent(data.keySet()); + + // delete operations + caffeine.invalidate("1"); + caffeine.invalidateAll(data.keySet()); + caffeine.invalidateAll(); + } catch (Exception e) { + throw e; + } + } +} diff --git a/test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/controller/HeartbeatController.java b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/controller/HeartbeatController.java new file mode 100644 index 0000000000..9dbc01dc77 --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/caffeine/controller/HeartbeatController.java @@ -0,0 +1,31 @@ +/* + * 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.testcase.caffeine.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HeartbeatController { + + @GetMapping("/case/healthCheck") + public String healthCheck() { + return "success"; + } +} diff --git a/test/plugin/scenarios/caffeine-3.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/resources/application.yaml new file mode 100755 index 0000000000..ac1fb9a734 --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,21 @@ +# +# 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 + servlet: + context-path: /caffeine-3.x-scenario \ No newline at end of file diff --git a/test/plugin/scenarios/caffeine-3.x-scenario/support-version.list b/test/plugin/scenarios/caffeine-3.x-scenario/support-version.list new file mode 100755 index 0000000000..0c44c26905 --- /dev/null +++ b/test/plugin/scenarios/caffeine-3.x-scenario/support-version.list @@ -0,0 +1,18 @@ +# 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. + +3.0.0 +3.1.8 \ No newline at end of file From b358267905be8748d105014cc3da066aacd33b46 Mon Sep 17 00:00:00 2001 From: weixiang1862 <652048614@qq.com> Date: Mon, 30 Dec 2024 21:13:09 +0800 Subject: [PATCH 051/114] Add Undertow 2.1.7.final+ worker thread pool metrics. (#744) --- CHANGES.md | 1 + .../pom.xml | 9 +- .../XnioWorkerConstructorInterceptor.java | 65 ++++++++++ ...dertowWorkerThreadPoolInstrumentation.java | 43 ++++--- .../XnioWorkerConstructorInstrumentation.java | 78 ++++++++++++ .../pool/util/XnioWorkerTaskPoolAccessor.java | 117 ++++++++++++++++++ .../src/main/resources/skywalking-plugin.def | 3 +- .../config/expectedData.yaml | 10 +- .../pom.xml | 2 +- 9 files changed, 305 insertions(+), 23 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/XnioWorkerConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/define/XnioWorkerConstructorInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/util/XnioWorkerTaskPoolAccessor.java diff --git a/CHANGES.md b/CHANGES.md index 8a74479321..007f7ca21a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ Release Notes. * Change context and parent entry span propagation mechanism from gRPC ThreadLocal context to SkyWalking native dynamic field as new propagation mechanism, to better support async scenarios. * Add Caffeine plugin as optional. +* Add Undertow 2.1.7.final+ worker thread pool metrics. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml index 06470ce5d3..d1c1359a35 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml @@ -29,5 +29,12 @@ undertow-worker-thread-pool-plugin http://maven.apache.org - + + + org.jboss.xnio + xnio-api + 3.8.4.Final + provided + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/XnioWorkerConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/XnioWorkerConstructorInterceptor.java new file mode 100644 index 0000000000..88cecc5ca1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/XnioWorkerConstructorInterceptor.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.undertow.worker.thread.pool; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Supplier; +import org.apache.skywalking.apm.agent.core.meter.MeterFactory; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.undertow.worker.thread.pool.util.XnioWorkerTaskPoolAccessor; +import org.xnio.XnioWorker; + +public class XnioWorkerConstructorInterceptor implements InstanceConstructorInterceptor { + + private static final String THREAD_POOL_NAME = "undertow_worker_pool"; + + private static final Map>> METRIC_MAP = new HashMap>>() {{ + put("core_pool_size", (XnioWorkerTaskPoolAccessor threadPoolExecutor) -> () -> (double) threadPoolExecutor.getCorePoolSize()); + put("max_pool_size", (XnioWorkerTaskPoolAccessor threadPoolExecutor) -> () -> (double) threadPoolExecutor.getMaximumPoolSize()); + put("pool_size", (XnioWorkerTaskPoolAccessor threadPoolExecutor) -> () -> (double) threadPoolExecutor.getPoolSize()); + put("queue_size", (XnioWorkerTaskPoolAccessor threadPoolExecutor) -> () -> (double) threadPoolExecutor.getQueueSize()); + put("active_size", (XnioWorkerTaskPoolAccessor threadPoolExecutor) -> () -> (double) threadPoolExecutor.getActiveCount()); + }}; + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + buildThreadPoolMeterMetric(new XnioWorkerTaskPoolAccessor((XnioWorker) objInst)); + } + + private void buildThreadPoolMeterMetric(XnioWorkerTaskPoolAccessor xnioWorkerTaskPoolAccessor) { + String threadPoolMeterName = "thread_pool"; + String poolNameTag = "pool_name"; + String metricTypeTag = "metric_type"; + METRIC_MAP.forEach((key, value) -> { + if (Objects.equals(key, "pool_size")) { + if (xnioWorkerTaskPoolAccessor.isContainsGetPoolSizeMethod()) { + MeterFactory.gauge(threadPoolMeterName, value.apply(xnioWorkerTaskPoolAccessor)) + .tag(poolNameTag, THREAD_POOL_NAME).tag(metricTypeTag, key).build(); + } + } else { + MeterFactory.gauge(threadPoolMeterName, value.apply(xnioWorkerTaskPoolAccessor)) + .tag(poolNameTag, THREAD_POOL_NAME).tag(metricTypeTag, key).build(); + } + }); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/define/UndertowWorkerThreadPoolInstrumentation.java b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/define/UndertowWorkerThreadPoolInstrumentation.java index edca92a998..ce827e349c 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/define/UndertowWorkerThreadPoolInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/define/UndertowWorkerThreadPoolInstrumentation.java @@ -19,43 +19,56 @@ package org.apache.skywalking.apm.plugin.undertow.worker.thread.pool.define; import static net.bytebuddy.matcher.ElementMatchers.any; -import static org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch; -import static org.apache.skywalking.apm.agent.core.plugin.match.PrefixMatch.nameStartsWith; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; +import java.util.Collections; +import java.util.List; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; 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.logical.LogicalMatchOperation; +/** + * ThreadPoolExecutor implemented xnio worker task pool before 3.6.0 + */ public class UndertowWorkerThreadPoolInstrumentation extends ClassEnhancePluginDefine { - private static final String THREAD_POOL_EXECUTOR_CLASS = "java.util.concurrent.ThreadPoolExecutor"; + private static final String THREAD_POOL_EXECUTOR_CLASS = "org.xnio.XnioWorker$TaskPool"; private static final String UNDERTOW_WORKER_THREAD_POOL_INTERCEPT = "org.apache.skywalking.apm.plugin.undertow.worker.thread.pool.UndertowWorkerThreadPoolConstructorIntercept"; + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + "org.xnio.XnioWorker$TaskPool", + named("terminated") + )); + } + @Override protected ClassMatch enhanceClass() { - return LogicalMatchOperation.and(nameStartsWith("org.xnio"), byHierarchyMatch(THREAD_POOL_EXECUTOR_CLASS)); + return byName(THREAD_POOL_EXECUTOR_CLASS); } @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[]{ - new ConstructorInterceptPoint() { - @Override - public ElementMatcher getConstructorMatcher() { - return any(); - } + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } - @Override - public String getConstructorInterceptor() { - return UNDERTOW_WORKER_THREAD_POOL_INTERCEPT; - } + @Override + public String getConstructorInterceptor() { + return UNDERTOW_WORKER_THREAD_POOL_INTERCEPT; } + } }; } diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/define/XnioWorkerConstructorInstrumentation.java b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/define/XnioWorkerConstructorInstrumentation.java new file mode 100644 index 0000000000..2bc13dd20f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/define/XnioWorkerConstructorInstrumentation.java @@ -0,0 +1,78 @@ +/* + * 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.undertow.worker.thread.pool.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.StaticMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * xnio task pool new implementation since 3.6.0 + * https://github.com/xnio/xnio/commit/071800e0a85c9da9b88a976ac7ecb85760924dbf + */ +public class XnioWorkerConstructorInstrumentation extends ClassEnhancePluginDefine { + + private static final String XNIO_WORKER_CLASS = "org.xnio.XnioWorker"; + + private static final String UNDERTOW_WORKER_THREAD_POOL_INTERCEPT = "org.apache.skywalking.apm.plugin.undertow.worker.thread.pool.XnioWorkerConstructorInterceptor"; + + @Override + protected String[] witnessClasses() { + return new String[] {"org.xnio.XnioWorker$EnhancedQueueExecutorTaskPool"}; + } + + @Override + protected ClassMatch enhanceClass() { + return byName(XNIO_WORKER_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return UNDERTOW_WORKER_THREAD_POOL_INTERCEPT; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + + @Override + public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() { + return new StaticMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/util/XnioWorkerTaskPoolAccessor.java b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/util/XnioWorkerTaskPoolAccessor.java new file mode 100644 index 0000000000..2284115437 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/java/org/apache/skywalking/apm/plugin/undertow/worker/thread/pool/util/XnioWorkerTaskPoolAccessor.java @@ -0,0 +1,117 @@ +/* + * 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.undertow.worker.thread.pool.util; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import lombok.Getter; +import org.xnio.XnioWorker; + +public class XnioWorkerTaskPoolAccessor { + + private final Object taskPool; + @Getter + private boolean containsGetPoolSizeMethod; + + private Method getCorePoolSizeMethod; + private Method getMaximumPoolSizeMethod; + private Method getActiveCountMethod; + private Method getPoolSizeMethod; + private Method getQueueSizeMethod; + + public XnioWorkerTaskPoolAccessor(final XnioWorker worker) throws NoSuchFieldException, IllegalAccessException { + Field field = worker.getClass().getSuperclass().getDeclaredField("taskPool"); + field.setAccessible(true); + this.taskPool = field.get(worker); + + try { + getCorePoolSizeMethod = taskPool.getClass().getDeclaredMethod("getCorePoolSize"); + getCorePoolSizeMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + // ignore + } + try { + getMaximumPoolSizeMethod = taskPool.getClass().getDeclaredMethod("getMaximumPoolSize"); + getMaximumPoolSizeMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + // ignore + } + try { + getActiveCountMethod = taskPool.getClass().getDeclaredMethod("getActiveCount"); + getActiveCountMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + // ignore + } + try { + // getPoolSize add since 3.8.0 + getPoolSizeMethod = taskPool.getClass().getDeclaredMethod("getPoolSize"); + getPoolSizeMethod.setAccessible(true); + containsGetPoolSizeMethod = true; + } catch (NoSuchMethodException e) { + containsGetPoolSizeMethod = false; + } + try { + getQueueSizeMethod = taskPool.getClass().getDeclaredMethod("getQueueSize"); + getQueueSizeMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + // ignore + } + } + + public int getCorePoolSize() { + try { + return (int) getCorePoolSizeMethod.invoke(taskPool); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public int getMaximumPoolSize() { + try { + return (int) getMaximumPoolSizeMethod.invoke(taskPool); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public int getActiveCount() { + try { + return (int) getActiveCountMethod.invoke(taskPool); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public int getPoolSize() { + try { + return (int) getPoolSizeMethod.invoke(taskPool); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + public int getQueueSize() { + try { + return (int) getQueueSizeMethod.invoke(taskPool); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/resources/skywalking-plugin.def index 22837a7aad..8ff6aacdbd 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/src/main/resources/skywalking-plugin.def @@ -14,4 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -undertow-worker-thread-pool=org.apache.skywalking.apm.plugin.undertow.worker.thread.pool.define.UndertowWorkerThreadPoolInstrumentation \ No newline at end of file +undertow-worker-thread-pool=org.apache.skywalking.apm.plugin.undertow.worker.thread.pool.define.UndertowWorkerThreadPoolInstrumentation +undertow-worker-thread-pool=org.apache.skywalking.apm.plugin.undertow.worker.thread.pool.define.XnioWorkerConstructorInstrumentation \ No newline at end of file diff --git a/test/plugin/scenarios/undertow-worker-thread-pool-scenario/config/expectedData.yaml b/test/plugin/scenarios/undertow-worker-thread-pool-scenario/config/expectedData.yaml index 424a39aee8..ba30823ec1 100644 --- a/test/plugin/scenarios/undertow-worker-thread-pool-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/undertow-worker-thread-pool-scenario/config/expectedData.yaml @@ -22,29 +22,29 @@ meterItems: tags: - {name: metric_type, value: core_pool_size} - {name: pool_name, value: undertow_worker_pool} - singleValue: ge 1 + singleValue: ge -1 - meterId: name: thread_pool tags: - {name: metric_type, value: max_pool_size} - {name: pool_name, value: undertow_worker_pool} - singleValue: ge 1 + singleValue: ge -1 - meterId: name: thread_pool tags: - {name: metric_type, value: pool_size} - {name: pool_name, value: undertow_worker_pool} - singleValue: ge 0 + singleValue: ge -1 - meterId: name: thread_pool tags: - {name: metric_type, value: active_size} - {name: pool_name, value: undertow_worker_pool} - singleValue: ge 0 + singleValue: ge -1 - meterId: name: thread_pool tags: - {name: metric_type, value: queue_size} - {name: pool_name, value: undertow_worker_pool} - singleValue: ge 0 + singleValue: ge -1 diff --git a/test/plugin/scenarios/undertow-worker-thread-pool-scenario/pom.xml b/test/plugin/scenarios/undertow-worker-thread-pool-scenario/pom.xml index 7babe86a4e..ff3f3f582e 100644 --- a/test/plugin/scenarios/undertow-worker-thread-pool-scenario/pom.xml +++ b/test/plugin/scenarios/undertow-worker-thread-pool-scenario/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-dependencies - ${spring-boot-version} + ${test.framework.version} pom import From 31bf638213a0c4de413e5765eac1c9bd8fd01e07 Mon Sep 17 00:00:00 2001 From: jiangyuan Date: Fri, 10 Jan 2025 23:39:35 +0800 Subject: [PATCH 052/114] Simplify plugin.dest.dir property in pom.xml (#746) --- apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/pom.xml | 5 +---- apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml | 1 - .../spring-plugins/spring-cloud/netflix-plugins/pom.xml | 1 - .../apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml | 1 - apm-sniffer/bootstrap-plugins/pom.xml | 5 +---- apm-sniffer/expired-plugins/pom.xml | 5 +---- .../optional-spring-plugins/optional-spring-cloud/pom.xml | 1 - apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml | 1 - apm-sniffer/optional-plugins/pom.xml | 5 +---- apm-sniffer/optional-reporter-plugins/pom.xml | 3 +-- 23 files changed, 5 insertions(+), 36 deletions(-) diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml index 677b9953d8..a3c50c7f1e 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml @@ -35,7 +35,6 @@ UTF-8 - /.. \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml index b5fcb7965e..d13e127585 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml @@ -37,6 +37,5 @@ UTF-8 - /.. \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml index aab144f839..b028d224fd 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml @@ -32,7 +32,6 @@ UTF-8 - /.. diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml index 93809620f5..fff2a09c61 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml @@ -27,7 +27,6 @@ 8 8 UTF-8 - /.. 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml index 59ea20b3db..21d38befca 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml @@ -41,6 +41,5 @@ UTF-8 - /.. diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml index b3eaf724c3..89f4778d13 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml @@ -37,6 +37,5 @@ UTF-8 - /.. diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml index a35c15c0e0..d4b2ff1753 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml @@ -29,7 +29,6 @@ UTF-8 - /.. diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml index aa0cf71596..273c4dd296 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml @@ -39,7 +39,6 @@ UTF-8 - /.. diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 203fb664f7..debaf5bf76 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -146,13 +146,10 @@ UTF-8 - net.bytebuddy ${shade.package}.${shade.net.bytebuddy.source} - ${project.build.directory}${sdk.plugin.related.dir}/../../../../skywalking-agent - - ${agent.package.dest.dir}/plugins + ${maven.multiModuleProjectDirectory}/skywalking-agent/plugins 1.0b3 1.8.1 diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml index 9c24d18dbe..25bd66f0a7 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml @@ -38,6 +38,5 @@ UTF-8 - /.. \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml index 607b2e50bd..fe95b1df3a 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml @@ -37,6 +37,5 @@ UTF-8 - /.. diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml index ff5e8625db..03d6992c14 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml @@ -36,6 +36,5 @@ UTF-8 - /.. diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml index 1325ebcb8d..daf2214ab2 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml @@ -53,7 +53,6 @@ UTF-8 - /.. diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml index f79b0b7985..f66650161e 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml @@ -37,7 +37,6 @@ UTF-8 - /../../.. diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml index 345b39b97b..bb5ebcf67b 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml @@ -38,7 +38,6 @@ UTF-8 - /../.. diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml index d1979611a1..e02b868b8d 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml @@ -37,6 +37,5 @@ UTF-8 - /.. diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml index 76e3334c3f..fa08a46702 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml @@ -38,7 +38,6 @@ UTF-8 - /.. diff --git a/apm-sniffer/bootstrap-plugins/pom.xml b/apm-sniffer/bootstrap-plugins/pom.xml index 5a12be422d..30625b1b5f 100644 --- a/apm-sniffer/bootstrap-plugins/pom.xml +++ b/apm-sniffer/bootstrap-plugins/pom.xml @@ -32,10 +32,7 @@ ${shade.package}.${shade.net.bytebuddy.source} UTF-8 - - ${project.build.directory}${sdk.plugin.related.dir}/../../../../skywalking-agent - - ${agent.package.dest.dir}/bootstrap-plugins + ${maven.multiModuleProjectDirectory}/skywalking-agent/bootstrap-plugins 1.0b3 1.8.1 diff --git a/apm-sniffer/expired-plugins/pom.xml b/apm-sniffer/expired-plugins/pom.xml index 5f991dde32..205ed460f1 100644 --- a/apm-sniffer/expired-plugins/pom.xml +++ b/apm-sniffer/expired-plugins/pom.xml @@ -32,10 +32,7 @@ ${shade.package}.${shade.net.bytebuddy.source} UTF-8 - - ${project.build.directory}${sdk.plugin.related.dir}/../../../../skywalking-agent - - ${agent.package.dest.dir}/expired-plugins + ${maven.multiModuleProjectDirectory}/skywalking-agent/expired-plugins 1.0b3 1.8.1 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml index d28ac5a57a..3554a8c1e0 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml @@ -40,7 +40,6 @@ UTF-8 - /../.. diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml index e4f16f60c9..a5f1256ee7 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml @@ -39,7 +39,6 @@ - /.. diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml index 6369484e82..05f41f83f9 100644 --- a/apm-sniffer/optional-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/pom.xml @@ -32,10 +32,7 @@ ${shade.package}.${shade.net.bytebuddy.source} UTF-8 - - ${project.build.directory}${sdk.plugin.related.dir}/../../../../skywalking-agent - - ${agent.package.dest.dir}/optional-plugins + ${maven.multiModuleProjectDirectory}/skywalking-agent/optional-plugins 1.0b3 1.8.1 diff --git a/apm-sniffer/optional-reporter-plugins/pom.xml b/apm-sniffer/optional-reporter-plugins/pom.xml index 4446e5b489..4cf950ba70 100644 --- a/apm-sniffer/optional-reporter-plugins/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/pom.xml @@ -36,8 +36,7 @@ UTF-8 - ${project.build.directory}/../../../../skywalking-agent - ${agent.package.dest.dir}/optional-reporter-plugins + ${maven.multiModuleProjectDirectory}/skywalking-agent/optional-reporter-plugins 1.0b3 1.8.1 From 35495375d05213e34017ab24d67554f0267dce4d Mon Sep 17 00:00:00 2001 From: yqw570994511 <49865334+yqw570994511@users.noreply.github.com> Date: Sat, 11 Jan 2025 18:09:42 +0800 Subject: [PATCH 053/114] [Feature] Support for tracking in spring gateway versions 4.1.2 and above (#747) --- .github/workflows/ci.yaml | 3 + .github/workflows/plugins-jdk17-test.1.yaml | 1 + CHANGES.md | 1 + .../define/GatewayFilterInstrumentation.java | 2 +- .../define/GatewayFilterInstrumentation.java | 2 +- .../define/GatewayFilterInstrumentation.java | 2 +- .../v412x/GatewayFilterV412Interceptor.java | 94 +++++ ...ClientConnectDuplicateV412Interceptor.java | 50 +++ ...tpClientConnectRequestV412Interceptor.java | 54 +++ ...ntFinalizerConstructorV412Interceptor.java | 43 +++ ...izerResponseConnectionV412Interceptor.java | 107 ++++++ ...ttpClientFinalizerSendV412Interceptor.java | 112 ++++++ ...HttpClientFinalizerUriV412Interceptor.java | 57 +++ .../NettyRoutingFilterV412Interceptor.java | 91 +++++ ...tyRoutingGetHttpClientV412Interceptor.java | 55 +++ ...bstractGatewayV412EnhancePluginDefine.java | 35 ++ .../GatewayFilterV412Instrumentation.java | 67 ++++ .../HttpClientConnectV412Instrumentation.java | 87 +++++ ...ttpClientFinalizerV412Instrumentation.java | 114 ++++++ ...NettyRoutingFilterV412Instrumentation.java | 89 +++++ .../AbstractGatewayV4EnhancePluginDefine.java | 15 + .../v4x/define/EnhanceObjectCache.java | 11 + .../define/GatewayFilterInstrumentation.java | 2 +- .../src/main/resources/skywalking-plugin.def | 4 + .../GatewayFilterV412InterceptorTest.java | 332 ++++++++++++++++++ ...ntConnectDuplicateV412InterceptorTest.java | 125 +++++++ ...ientConnectRequestV412InterceptorTest.java | 165 +++++++++ ...nalizerConstructorV412InterceptorTest.java | 68 ++++ ...ClientFinalizerUriV412InterceptorTest.java | 176 ++++++++++ ...ttpClientFinalizerV412InterceptorTest.java | 204 +++++++++++ .../gateway/v412x/MockClientRequest.java | 135 +++++++ .../gateway/v412x/MockClientResponse.java | 120 +++++++ ...NettyRoutingFilterV412InterceptorTest.java | 222 ++++++++++++ ...utingGetHttpClientV412InterceptorTest.java | 115 ++++++ .../config/expectedData.yaml | 155 ++++++++ .../configuration.yml | 22 ++ .../gateway-dist/bin/startup.sh | 24 ++ .../gateway-dist/pom.xml | 54 +++ .../src/main/assembly/assembly.xml | 46 +++ .../gateway-projectA-scenario/pom.xml | 56 +++ .../sc/gateway/projectA/ApiKeyResolver.java | 31 ++ .../sc/gateway/projectA/Application.java | 29 ++ .../sc/gateway/projectA/Test1Filter.java | 38 ++ .../sc/gateway/projectA/Test2Filter.java | 39 ++ .../sc/gateway/projectA/TestFilterConfig.java | 35 ++ .../src/main/resources/application.yml | 33 ++ .../gateway-projectB-scenario/pom.xml | 57 +++ .../sc/gateway/projectB/Application.java | 31 ++ .../projectB/controller/TestController.java | 40 +++ .../src/main/resources/application.properties | 17 + .../gateway-4.1.2.x-scenario/pom.xml | 59 ++++ .../support-version.list | 19 + .../gateway-4.x-scenario/support-version.list | 3 +- 53 files changed, 3543 insertions(+), 5 deletions(-) create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/GatewayFilterV412Interceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectDuplicateV412Interceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectRequestV412Interceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerConstructorV412Interceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerResponseConnectionV412Interceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerSendV412Interceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerUriV412Interceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingFilterV412Interceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingGetHttpClientV412Interceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/AbstractGatewayV412EnhancePluginDefine.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/GatewayFilterV412Instrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/HttpClientConnectV412Instrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/HttpClientFinalizerV412Instrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/NettyRoutingFilterV412Instrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/GatewayFilterV412InterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectDuplicateV412InterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectRequestV412InterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerConstructorV412InterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerUriV412InterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerV412InterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/MockClientRequest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/MockClientResponse.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingFilterV412InterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingGetHttpClientV412InterceptorTest.java create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/bin/startup.sh create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/pom.xml create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/pom.xml create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/pom.xml create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/gateway-4.1.2.x-scenario/support-version.list diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e2078dd4ab..b92e5370de 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -53,6 +53,9 @@ jobs: - os: ubuntu java-version: 21 steps: + - if: matrix.os == 'windows' + name: Support longpaths + run: git config --system core.longpaths true - uses: actions/checkout@v2 with: submodules: true diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index 80ff29bb67..418da87f35 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -58,6 +58,7 @@ jobs: - spring-6.x-scenario - resteasy-6.x-scenario - gateway-4.x-scenario + - gateway-4.1.2.x-scenario - httpexchange-scenario - activemq-artemis-2.x-scenario - c3p0-0.9.0.x-0.9.1.x-scenario diff --git a/CHANGES.md b/CHANGES.md index 007f7ca21a..4fd1859d4c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -27,6 +27,7 @@ Release Notes. field as new propagation mechanism, to better support async scenarios. * Add Caffeine plugin as optional. * Add Undertow 2.1.7.final+ worker thread pool metrics. +* Support for tracking in spring gateway versions 4.1.2 and above. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/GatewayFilterInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/GatewayFilterInstrumentation.java index 3e303d8df3..5435af8a08 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/GatewayFilterInstrumentation.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/GatewayFilterInstrumentation.java @@ -56,7 +56,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return true; + return false; } } }; diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/GatewayFilterInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/GatewayFilterInstrumentation.java index 62d562c0b0..1031478c4a 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/GatewayFilterInstrumentation.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/define/GatewayFilterInstrumentation.java @@ -56,7 +56,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return true; + return false; } } }; diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/GatewayFilterInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/GatewayFilterInstrumentation.java index 644d844f35..4488516f19 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/GatewayFilterInstrumentation.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/GatewayFilterInstrumentation.java @@ -59,7 +59,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return true; + return false; } } }; diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/GatewayFilterV412Interceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/GatewayFilterV412Interceptor.java new file mode 100644 index 0000000000..c1a9ec505f --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/GatewayFilterV412Interceptor.java @@ -0,0 +1,94 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.ServerWebExchangeDecorator; +import org.springframework.web.server.adapter.DefaultServerWebExchange; + +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.apache.skywalking.apm.network.trace.component.ComponentsDefine.SPRING_CLOUD_GATEWAY; + +public class GatewayFilterV412Interceptor implements InstanceMethodsAroundInterceptor { + + private static final ThreadLocal STACK_DEEP = ThreadLocal.withInitial(() -> new AtomicInteger(0)); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + if (isEntry()) { + ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; + + EnhancedInstance enhancedInstance = getInstance(exchange); + + AbstractSpan span = ContextManager.createLocalSpan("SpringCloudGateway/GatewayFilter"); + if (enhancedInstance != null && enhancedInstance.getSkyWalkingDynamicField() != null) { + ContextManager.continued((ContextSnapshot) enhancedInstance.getSkyWalkingDynamicField()); + } + span.setComponent(SPRING_CLOUD_GATEWAY); + } + } + + public static EnhancedInstance getInstance(Object o) { + EnhancedInstance instance = null; + if (o instanceof DefaultServerWebExchange) { + instance = (EnhancedInstance) o; + } else if (o instanceof ServerWebExchangeDecorator) { + ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate(); + return getInstance(delegate); + } + return instance; + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (isExit()) { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + } + + private boolean isEntry() { + return STACK_DEEP.get().getAndIncrement() == 0; + } + + private boolean isExit() { + boolean isExit = STACK_DEEP.get().decrementAndGet() == 0; + if (isExit) { + STACK_DEEP.remove(); + } + return isExit; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectDuplicateV412Interceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectDuplicateV412Interceptor.java new file mode 100644 index 0000000000..5658134748 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectDuplicateV412Interceptor.java @@ -0,0 +1,50 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; + +import java.lang.reflect.Method; + +public class HttpClientConnectDuplicateV412Interceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + if (objInst.getSkyWalkingDynamicField() != null) { + EnhanceObjectCache enhanceObjectCache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField(); + if (ret instanceof EnhancedInstance) { + EnhancedInstance retEnhancedInstance = (EnhancedInstance) ret; + retEnhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache); + } + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectRequestV412Interceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectRequestV412Interceptor.java new file mode 100644 index 0000000000..f35f3551fb --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectRequestV412Interceptor.java @@ -0,0 +1,54 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; + +import java.lang.reflect.Method; + +public class HttpClientConnectRequestV412Interceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + if (objInst.getSkyWalkingDynamicField() != null) { + if (ret instanceof EnhancedInstance) { + EnhancedInstance retEnhancedInstance = (EnhancedInstance) ret; + Object retSkyWalkingDynamicField = retEnhancedInstance.getSkyWalkingDynamicField(); + if (retSkyWalkingDynamicField != null) { + EnhanceObjectCache retEnhanceObjectCache = (EnhanceObjectCache) retSkyWalkingDynamicField; + EnhanceObjectCache objEnhanceObjectCache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField(); + retEnhanceObjectCache.setContextSnapshot(objEnhanceObjectCache.getContextSnapshot()); + } + } + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerConstructorV412Interceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerConstructorV412Interceptor.java new file mode 100644 index 0000000000..410baa61a7 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerConstructorV412Interceptor.java @@ -0,0 +1,43 @@ +/* + * 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.spring.cloud.gateway.v412x; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; +import reactor.netty.http.client.HttpClientConfig; + +/** + * Intercept the constructor and inject {@link EnhanceObjectCache}. + *

+ * The first constructor argument is {@link HttpClientConfig} class instance which can get the + * request uri string. + */ +public class HttpClientFinalizerConstructorV412Interceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + final HttpClientConfig httpClientConfig = (HttpClientConfig) allArguments[0]; + if (httpClientConfig == null) { + return; + } + final EnhanceObjectCache enhanceObjectCache = new EnhanceObjectCache(); + enhanceObjectCache.setUrl(httpClientConfig.uri()); + objInst.setSkyWalkingDynamicField(enhanceObjectCache); + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerResponseConnectionV412Interceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerResponseConnectionV412Interceptor.java new file mode 100644 index 0000000000..7199c85744 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerResponseConnectionV412Interceptor.java @@ -0,0 +1,107 @@ +/* + * 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.spring.cloud.gateway.v412x; + +import io.netty.handler.codec.http.HttpResponseStatus; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +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.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; +import org.reactivestreams.Publisher; +import reactor.core.publisher.Flux; +import reactor.core.publisher.SignalType; +import reactor.netty.Connection; +import reactor.netty.http.client.HttpClientResponse; + +import java.lang.reflect.Method; +import java.util.function.BiFunction; + +/** + * This class intercept responseConnection method. + *

+ * After downstream service response, finish the span in the {@link EnhanceObjectCache}. + */ +public class HttpClientFinalizerResponseConnectionV412Interceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) { + BiFunction finalReceiver = (BiFunction) allArguments[0]; + EnhanceObjectCache cache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField(); + allArguments[0] = (BiFunction) (response, connection) -> { + Publisher publisher = finalReceiver.apply(response, connection); + if (cache == null) { + return publisher; + } + // receive the response. + if (cache.getSpan() != null) { + if (response.status().code() >= HttpResponseStatus.BAD_REQUEST.code()) { + cache.getSpan().errorOccurred(); + } + Tags.HTTP_RESPONSE_STATUS_CODE.set(cache.getSpan(), response.status().code()); + } + + return publisher; + }; + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) { + Flux responseFlux = (Flux) ret; + + responseFlux = responseFlux + .doOnError(e -> { + EnhanceObjectCache cache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField(); + if (cache == null) { + return; + } + + if (cache.getSpan() != null) { + cache.getSpan().errorOccurred(); + cache.getSpan().log(e); + } + }) + .doFinally(signalType -> { + EnhanceObjectCache cache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField(); + if (cache == null) { + return; + } + // do finally. Finish the span. + if (cache.getSpan() != null) { + if (signalType == SignalType.CANCEL) { + cache.getSpan().errorOccurred(); + } + cache.getSpan().asyncFinish(); + } + + if (cache.getSpan1() != null) { + cache.getSpan1().asyncFinish(); + } + }); + + return responseFlux; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerSendV412Interceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerSendV412Interceptor.java new file mode 100644 index 0000000000..a1bc32f329 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerSendV412Interceptor.java @@ -0,0 +1,112 @@ +/* + * 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.spring.cloud.gateway.v412x; + +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +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.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; +import org.apache.skywalking.apm.util.StringUtil; +import org.reactivestreams.Publisher; +import reactor.netty.NettyOutbound; +import reactor.netty.http.client.HttpClientRequest; + +import java.lang.reflect.Method; +import java.net.URL; +import java.util.function.BiFunction; + +import static org.apache.skywalking.apm.network.trace.component.ComponentsDefine.SPRING_CLOUD_GATEWAY; + +/** + * This class intercept send method. + *

+ * In before method, create a new BiFunction lambda expression for setting ContextCarrier to http header + * and replace the original lambda in argument + */ +public class HttpClientFinalizerSendV412Interceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + EnhanceObjectCache enhanceObjectCache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField(); + if (enhanceObjectCache == null) { + return; + } + ContextSnapshot contextSnapshot = enhanceObjectCache.getContextSnapshot(); + if (contextSnapshot == null) { + return; + } + AbstractSpan span = ContextManager.createLocalSpan("SpringCloudGateway/send"); + ContextManager.continued(contextSnapshot); + span.setComponent(SPRING_CLOUD_GATEWAY); + span.prepareForAsync(); + + if (StringUtil.isNotEmpty(enhanceObjectCache.getUrl())) { + URL url = new URL(enhanceObjectCache.getUrl()); + + ContextCarrier contextCarrier = new ContextCarrier(); + AbstractSpan abstractSpan = ContextManager.createExitSpan( + "SpringCloudGateway/sendRequest", contextCarrier, getPeer(url)); + Tags.URL.set(abstractSpan, enhanceObjectCache.getUrl()); + abstractSpan.prepareForAsync(); + abstractSpan.setComponent(SPRING_CLOUD_GATEWAY); + abstractSpan.setLayer(SpanLayer.HTTP); + ContextManager.stopSpan(abstractSpan); + + BiFunction> finalSender = (BiFunction>) allArguments[0]; + allArguments[0] = (BiFunction>) (request, outbound) -> { + Publisher publisher = finalSender.apply(request, outbound); + + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + request.requestHeaders().remove(next.getHeadKey()); + request.requestHeaders().set(next.getHeadKey(), next.getHeadValue()); + } + return publisher; + }; + enhanceObjectCache.setCacheSpan(abstractSpan); + } + ContextManager.stopSpan(span); + enhanceObjectCache.setSpan1(span); + } + + private String getPeer(URL url) { + return url.getHost() + ":" + url.getPort(); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) { + ((EnhancedInstance) ret).setSkyWalkingDynamicField(objInst.getSkyWalkingDynamicField()); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerUriV412Interceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerUriV412Interceptor.java new file mode 100644 index 0000000000..1d5c020210 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerUriV412Interceptor.java @@ -0,0 +1,57 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; + +import java.lang.reflect.Method; + +/** + * This class intercept uri method to get the url of downstream service + */ +public class HttpClientFinalizerUriV412Interceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (ret instanceof EnhancedInstance) { + EnhanceObjectCache retEnhanceObjectCache = (EnhanceObjectCache) ((EnhancedInstance) ret).getSkyWalkingDynamicField(); + if (retEnhanceObjectCache != null) { + retEnhanceObjectCache.setUrl(String.valueOf(allArguments[0])); + if (objInst.getSkyWalkingDynamicField() != null) { + EnhanceObjectCache objInstEnhanceObjectCache = (EnhanceObjectCache) objInst.getSkyWalkingDynamicField(); + retEnhanceObjectCache.setContextSnapshot(objInstEnhanceObjectCache.getContextSnapshot()); + } + } + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingFilterV412Interceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingFilterV412Interceptor.java new file mode 100644 index 0000000000..1d6aa76da8 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingFilterV412Interceptor.java @@ -0,0 +1,91 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.ServerWebExchangeDecorator; + +import java.lang.reflect.Method; + +import static org.apache.skywalking.apm.network.trace.component.ComponentsDefine.SPRING_CLOUD_GATEWAY; + +public class NettyRoutingFilterV412Interceptor implements InstanceMethodsAroundInterceptor { + + private static final String NETTY_ROUTING_FILTER_TRACED_ATTR = NettyRoutingFilterV412Interceptor.class.getName() + ".isTraced"; + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; + if (isTraced(exchange)) { + return; + } + + setTracedStatus(exchange); + + EnhancedInstance enhancedInstance = getInstance(allArguments[0]); + + AbstractSpan span = ContextManager.createLocalSpan("SpringCloudGateway/RoutingFilter"); + if (enhancedInstance != null && enhancedInstance.getSkyWalkingDynamicField() != null) { + ContextManager.continued((ContextSnapshot) enhancedInstance.getSkyWalkingDynamicField()); + } + span.setComponent(SPRING_CLOUD_GATEWAY); + } + + private static void setTracedStatus(ServerWebExchange exchange) { + exchange.getAttributes().put(NETTY_ROUTING_FILTER_TRACED_ATTR, true); + } + + private static boolean isTraced(ServerWebExchange exchange) { + return exchange.getAttributeOrDefault(NETTY_ROUTING_FILTER_TRACED_ATTR, false); + } + + private EnhancedInstance getInstance(Object o) { + EnhancedInstance instance = null; + if (o instanceof EnhancedInstance) { + instance = (EnhancedInstance) o; + } else if (o instanceof ServerWebExchangeDecorator) { + ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate(); + return getInstance(delegate); + } + return instance; + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (ContextManager.isActive()) { + // if HttpClientFinalizerSendInterceptor does not invoke, we will stop the span there to avoid context leak. + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingGetHttpClientV412Interceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingGetHttpClientV412Interceptor.java new file mode 100644 index 0000000000..282e6f5f17 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingGetHttpClientV412Interceptor.java @@ -0,0 +1,55 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.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.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; + +import java.lang.reflect.Method; + +public class NettyRoutingGetHttpClientV412Interceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + if (ret instanceof EnhancedInstance) { + if (ContextManager.isActive()) { + ContextSnapshot contextSnapshot = ContextManager.capture(); + EnhanceObjectCache retEnhanceObjectCache = new EnhanceObjectCache(); + retEnhanceObjectCache.setContextSnapshot(contextSnapshot); + EnhancedInstance retEnhancedInstance = (EnhancedInstance) ret; + retEnhancedInstance.setSkyWalkingDynamicField(retEnhanceObjectCache); + } + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + } + +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/AbstractGatewayV412EnhancePluginDefine.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/AbstractGatewayV412EnhancePluginDefine.java new file mode 100644 index 0000000000..7cde134ef8 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/AbstractGatewayV412EnhancePluginDefine.java @@ -0,0 +1,35 @@ +/* + * 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.spring.cloud.gateway.v412x.define; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; + +/** + * This abstract class defines the witnessClasses() method, + * and other plugin define classes need to inherit from this class + */ +public abstract class AbstractGatewayV412EnhancePluginDefine extends ClassInstanceMethodsEnhancePluginDefine { + + /** + * @since 4.0.0 + */ + @Override + protected String[] witnessClasses() { + return new String[]{"org.springframework.cloud.gateway.event.RouteDeletedEvent"}; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/GatewayFilterV412Instrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/GatewayFilterV412Instrumentation.java new file mode 100644 index 0000000000..499502a07d --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/GatewayFilterV412Instrumentation.java @@ -0,0 +1,67 @@ +/* + * 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.spring.cloud.gateway.v412x.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.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 GatewayFilterV412Instrumentation extends AbstractGatewayV412EnhancePluginDefine { + + private static final String INTERCEPT_CLASS_GATEWAY_FILTER = "org.springframework.cloud.gateway.filter.GatewayFilter"; + private static final String GATEWAY_FILTER_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.GatewayFilterV412Interceptor"; + + @Override + protected ClassMatch enhanceClass() { + return HierarchyMatch.byHierarchyMatch(INTERCEPT_CLASS_GATEWAY_FILTER); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("filter").and( + takesArgumentWithType(0, "org.springframework.web.server.ServerWebExchange")); + } + + @Override + public String getMethodsInterceptor() { + return GATEWAY_FILTER_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/HttpClientConnectV412Instrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/HttpClientConnectV412Instrumentation.java new file mode 100644 index 0000000000..3d1bb3462b --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/HttpClientConnectV412Instrumentation.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.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.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.returns; +import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class HttpClientConnectV412Instrumentation extends AbstractGatewayV412EnhancePluginDefine { + + private static final String ENHANCE_CLASS = "reactor.netty.http.client.HttpClientConnect"; + private static final String HTTP_CLIENT_CONNECT_DUPLICATE_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.HttpClientConnectDuplicateV412Interceptor"; + private static final String HTTP_CLIENT_CONNECT_REQUEST_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.HttpClientConnectRequestV412Interceptor"; + + @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 getMethodsMatcher() { + return named("duplicate").and(takesNoArguments()) + .and(returns(named("reactor.netty.http.client.HttpClient"))); + } + + @Override + public String getMethodsInterceptor() { + return HTTP_CLIENT_CONNECT_DUPLICATE_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("request").and(takesArgumentWithType(0, "io.netty.handler.codec.http.HttpMethod")) + .and(returns(named("reactor.netty.http.client.HttpClient$RequestSender"))); + } + + @Override + public String getMethodsInterceptor() { + return HTTP_CLIENT_CONNECT_REQUEST_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/HttpClientFinalizerV412Instrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/HttpClientFinalizerV412Instrumentation.java new file mode 100644 index 0000000000..7a5b9b888e --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/HttpClientFinalizerV412Instrumentation.java @@ -0,0 +1,114 @@ +/* + * 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.spring.cloud.gateway.v412x.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.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class HttpClientFinalizerV412Instrumentation extends AbstractGatewayV412EnhancePluginDefine { + + private static final String INTERCEPT_CLASS_HTTP_CLIENT_FINALIZER = "reactor.netty.http.client.HttpClientFinalizer"; + private static final String CLIENT_FINALIZER_CONSTRUCTOR_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.HttpClientFinalizerConstructorV412Interceptor"; + private static final String CLIENT_FINALIZER_CONSTRUCTOR_ARGUMENT_TYPE = "reactor.netty.http.client.HttpClientConfig"; + private static final String HTTP_CLIENT_FINALIZER_URI_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.HttpClientFinalizerUriV412Interceptor"; + private static final String HTTP_CLIENT_FINALIZER_SEND_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.HttpClientFinalizerSendV412Interceptor"; + private static final String HTTP_CLIENT_FINALIZER_RESPONSE_CONNECTION_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.HttpClientFinalizerResponseConnectionV412Interceptor"; + + @Override + protected ClassMatch enhanceClass() { + return byName(INTERCEPT_CLASS_HTTP_CLIENT_FINALIZER); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgumentWithType(0, CLIENT_FINALIZER_CONSTRUCTOR_ARGUMENT_TYPE); + } + + @Override + public String getConstructorInterceptor() { + return CLIENT_FINALIZER_CONSTRUCTOR_INTERCEPTOR; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("uri"); + } + + @Override + public String getMethodsInterceptor() { + return HTTP_CLIENT_FINALIZER_URI_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("send").and(takesArgumentWithType(0, "java.util.function.BiFunction")); + } + + @Override + public String getMethodsInterceptor() { + return HTTP_CLIENT_FINALIZER_SEND_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("responseConnection"); + } + + @Override + public String getMethodsInterceptor() { + return HTTP_CLIENT_FINALIZER_RESPONSE_CONNECTION_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/NettyRoutingFilterV412Instrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/NettyRoutingFilterV412Instrumentation.java new file mode 100644 index 0000000000..ca06147ba3 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/define/NettyRoutingFilterV412Instrumentation.java @@ -0,0 +1,89 @@ +/* + * 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.spring.cloud.gateway.v412x.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.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.returns; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class NettyRoutingFilterV412Instrumentation extends AbstractGatewayV412EnhancePluginDefine { + + private static final String INTERCEPT_CLASS_NETTY_ROUTING_FILTER = "org.springframework.cloud.gateway.filter.NettyRoutingFilter"; + private static final String NETTY_ROUTING_FILTER_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.NettyRoutingFilterV412Interceptor"; + private static final String NETTY_ROUTING_GET_HTTP_CLIENT_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.NettyRoutingGetHttpClientV412Interceptor"; + + @Override + protected ClassMatch enhanceClass() { + return byName(INTERCEPT_CLASS_NETTY_ROUTING_FILTER); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("filter").and( + takesArgumentWithType(0, "org.springframework.web.server.ServerWebExchange")); + } + + @Override + public String getMethodsInterceptor() { + return NETTY_ROUTING_FILTER_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("getHttpClient") + .and(takesArgumentWithType(0, "org.springframework.cloud.gateway.route.Route")) + .and(takesArgumentWithType(1, "org.springframework.web.server.ServerWebExchange")) + .and(returns(named("reactor.netty.http.client.HttpClient"))); + } + + @Override + public String getMethodsInterceptor() { + return NETTY_ROUTING_GET_HTTP_CLIENT_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/AbstractGatewayV4EnhancePluginDefine.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/AbstractGatewayV4EnhancePluginDefine.java index 803097ba62..f40d8832d4 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/AbstractGatewayV4EnhancePluginDefine.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/AbstractGatewayV4EnhancePluginDefine.java @@ -17,8 +17,15 @@ package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import java.util.Collections; +import java.util.List; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.returns; + /** * This abstract class defines the witnessClasses() method, * and other plugin define classes need to inherit from this class @@ -32,4 +39,12 @@ public abstract class AbstractGatewayV4EnhancePluginDefine extends ClassInstance protected String[] witnessClasses() { return new String[]{"org.springframework.cloud.gateway.filter.factory.cache.LocalResponseCacheProperties"}; } + + @Override + protected List witnessMethods() { + return Collections.singletonList( + new WitnessMethod("org.springframework.cloud.gateway.config.LocalResponseCacheAutoConfiguration", + named("responseCacheSizeWeigher"). + and(returns(named("org.springframework.cloud.gateway.filter.factory.cache.ResponseCacheSizeWeigher"))))); + } } diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/EnhanceObjectCache.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/EnhanceObjectCache.java index 419d5118a2..335d5ab6cd 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/EnhanceObjectCache.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/EnhanceObjectCache.java @@ -17,6 +17,7 @@ package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; /** @@ -27,6 +28,7 @@ public class EnhanceObjectCache { private String url; private AbstractSpan span; private AbstractSpan span1; + private ContextSnapshot contextSnapshot; public String getUrl() { return url; @@ -51,4 +53,13 @@ public AbstractSpan getSpan1() { public void setSpan1(final AbstractSpan span) { span1 = span; } + + public ContextSnapshot getContextSnapshot() { + return contextSnapshot; + } + + public void setContextSnapshot(final ContextSnapshot contextSnapshot) { + this.contextSnapshot = contextSnapshot; + } + } diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/GatewayFilterInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/GatewayFilterInstrumentation.java index 5a61b89ac1..e6bbde9c8a 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/GatewayFilterInstrumentation.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v4x/define/GatewayFilterInstrumentation.java @@ -59,7 +59,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return true; + return false; } } }; diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/resources/skywalking-plugin.def index a335a6b336..bbb2bb4cf9 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/main/resources/skywalking-plugin.def @@ -19,3 +19,7 @@ spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.ServerWebExchangeInstrumentation spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.DispatcherHandlerInstrumentation spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.GatewayFilterInstrumentation +spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.define.HttpClientFinalizerV412Instrumentation +spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.define.NettyRoutingFilterV412Instrumentation +spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.define.GatewayFilterV412Instrumentation +spring-cloud-gateway-4.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v412x.define.HttpClientConnectV412Instrumentation diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/GatewayFilterV412InterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/GatewayFilterV412InterceptorTest.java new file mode 100644 index 0000000000..d8265ee075 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/GatewayFilterV412InterceptorTest.java @@ -0,0 +1,332 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.springframework.context.ApplicationContext; +import org.springframework.context.i18n.LocaleContext; +import org.springframework.http.codec.multipart.Part; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebSession; +import reactor.core.publisher.Mono; + +import java.security.Principal; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +@RunWith(TracingSegmentRunner.class) +public class GatewayFilterV412InterceptorTest { + + private static final String GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME = "SpringCloudGateway/GatewayFilter"; + + private static class ServerWebExchangeEnhancedInstance implements ServerWebExchange, EnhancedInstance { + private ContextSnapshot snapshot; + Map attributes = new HashMap<>(); + + @Override + public Object getSkyWalkingDynamicField() { + return snapshot; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.snapshot = (ContextSnapshot) value; + } + + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + } + + private final ServerWebExchangeEnhancedInstance enhancedInstance = new ServerWebExchangeEnhancedInstance(); + private final GatewayFilterV412Interceptor interceptor = new GatewayFilterV412Interceptor(); + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Before + public void setUp() throws Exception { + } + + private final ServerWebExchange exchange = new ServerWebExchange() { + Map attributes = new HashMap<>(); + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + }; + + @Test + public void testInterceptOnlyOnce() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{exchange}, null, null); + Assert.assertTrue(ContextManager.isActive()); + AbstractSpan activeSpan = ContextManager.activeSpan(); + Assert.assertTrue(activeSpan instanceof AbstractTracingSpan); + Assert.assertEquals(activeSpan.getOperationName(), GATEWAY_FILTER_INTERCEPTOR_LOCAL_SPAN_OPERATION_NAME); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + + } + + @Test + public void testNestedInterception() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertTrue(ContextManager.isActive()); + + interceptor.afterMethod(null, null, null, null, null); + Assert.assertFalse(ContextManager.isActive()); + + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithNullDynamicField() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 1); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithContextSnapshot() throws Throwable { + final AbstractSpan entrySpan = ContextManager.createEntrySpan("/get", null); + SpanLayer.asHttp(entrySpan); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + enhancedInstance.setSkyWalkingDynamicField(ContextManager.capture()); + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + ContextManager.stopSpan(entrySpan); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 2); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + SpanAssert.assertComponent(spans.get(1), ComponentsDefine.SPRING_WEBFLUX); + SpanAssert.assertLayer(spans.get(1), SpanLayer.HTTP); + } + +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectDuplicateV412InterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectDuplicateV412InterceptorTest.java new file mode 100644 index 0000000000..8cf3e9d830 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectDuplicateV412InterceptorTest.java @@ -0,0 +1,125 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +@RunWith(TracingSegmentRunner.class) +public class HttpClientConnectDuplicateV412InterceptorTest { + + private final static String ENTRY_OPERATION_NAME = "/get"; + private final HttpClientConnectDuplicateV412Interceptor duplicateInterceptor = new HttpClientConnectDuplicateV412Interceptor(); + private final EnhancedInstance enhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + private final EnhancedInstance retEnhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + private AbstractSpan entrySpan; + + @Before + public void setUp() throws Exception { + entrySpan = ContextManager.createEntrySpan(ENTRY_OPERATION_NAME, null); + entrySpan.setLayer(SpanLayer.HTTP); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + } + + @Test + public void testWithDynamicFieldNull() throws Throwable { + enhancedInstance.setSkyWalkingDynamicField(null); + duplicateInterceptor.afterMethod(enhancedInstance, null, null, null, retEnhancedInstance); + assertNull(retEnhancedInstance.getSkyWalkingDynamicField()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + + @Test + public void testWithDynamicFieldNotNull() throws Throwable { + ContextSnapshot contextSnapshot = ContextManager.capture(); + EnhanceObjectCache enhanceObjectCache = new EnhanceObjectCache(); + enhanceObjectCache.setContextSnapshot(contextSnapshot); + enhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache); + duplicateInterceptor.afterMethod(enhancedInstance, null, null, null, retEnhancedInstance); + Object retEnhancedInstanceSkyWalkingDynamicField = retEnhancedInstance.getSkyWalkingDynamicField(); + assertNotNull(retEnhancedInstanceSkyWalkingDynamicField); + assertTrue(retEnhancedInstanceSkyWalkingDynamicField instanceof EnhanceObjectCache); + EnhanceObjectCache retEnhanceObjectCache = (EnhanceObjectCache) retEnhancedInstanceSkyWalkingDynamicField; + assertNotNull(retEnhanceObjectCache.getContextSnapshot()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectRequestV412InterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectRequestV412InterceptorTest.java new file mode 100644 index 0000000000..06668c1eb2 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientConnectRequestV412InterceptorTest.java @@ -0,0 +1,165 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +@RunWith(TracingSegmentRunner.class) +public class HttpClientConnectRequestV412InterceptorTest { + private final static String URI = "http://localhost:8080/get"; + private final static String ENTRY_OPERATION_NAME = "/get"; + private final HttpClientConnectRequestV412Interceptor requestInterceptor = new HttpClientConnectRequestV412Interceptor(); + private final EnhancedInstance enhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + private final EnhancedInstance retEnhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + private AbstractSpan entrySpan; + + @Before + public void setUp() throws Exception { + entrySpan = ContextManager.createEntrySpan(ENTRY_OPERATION_NAME, null); + entrySpan.setLayer(SpanLayer.HTTP); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + } + + @Test + public void testWithDynamicFieldNull() throws Throwable { + enhancedInstance.setSkyWalkingDynamicField(null); + retEnhancedInstance.setSkyWalkingDynamicField(null); + requestInterceptor.afterMethod(enhancedInstance, null, null, null, retEnhancedInstance); + assertNull(retEnhancedInstance.getSkyWalkingDynamicField()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + + @Test + public void testWithRetDynamicFieldNotNull() throws Throwable { + enhancedInstance.setSkyWalkingDynamicField(null); + EnhanceObjectCache retEnhanceObjectCache = new EnhanceObjectCache(); + retEnhancedInstance.setSkyWalkingDynamicField(retEnhanceObjectCache); + + requestInterceptor.afterMethod(enhancedInstance, null, null, null, retEnhancedInstance); + assertNotNull(retEnhancedInstance.getSkyWalkingDynamicField()); + assertTrue(retEnhancedInstance.getSkyWalkingDynamicField() instanceof EnhanceObjectCache); + assertNull(((EnhanceObjectCache) retEnhancedInstance.getSkyWalkingDynamicField()).getContextSnapshot()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + + @Test + public void testWithDynamicFieldNotNull() throws Throwable { + ContextSnapshot contextSnapshot = ContextManager.capture(); + EnhanceObjectCache enhanceObjectCache = new EnhanceObjectCache(); + enhanceObjectCache.setContextSnapshot(contextSnapshot); + enhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache); + + EnhanceObjectCache enhanceObjectCache2 = new EnhanceObjectCache(); + enhanceObjectCache2.setUrl(URI); + retEnhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache2); + requestInterceptor.afterMethod(enhancedInstance, null, null, null, retEnhancedInstance); + Object retEnhancedInstanceSkyWalkingDynamicField = retEnhancedInstance.getSkyWalkingDynamicField(); + assertNotNull(retEnhancedInstanceSkyWalkingDynamicField); + assertTrue(retEnhancedInstanceSkyWalkingDynamicField instanceof EnhanceObjectCache); + EnhanceObjectCache retEnhanceObjectCache = (EnhanceObjectCache) retEnhancedInstanceSkyWalkingDynamicField; + assertNotNull(retEnhanceObjectCache.getContextSnapshot()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + + @Test + public void testWithRetDynamicFieldNull() throws Throwable { + ContextSnapshot contextSnapshot = ContextManager.capture(); + EnhanceObjectCache enhanceObjectCache = new EnhanceObjectCache(); + enhanceObjectCache.setContextSnapshot(contextSnapshot); + enhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache); + retEnhancedInstance.setSkyWalkingDynamicField(null); + + requestInterceptor.afterMethod(enhancedInstance, null, null, null, retEnhancedInstance); + Object retEnhancedInstanceSkyWalkingDynamicField = retEnhancedInstance.getSkyWalkingDynamicField(); + assertNull(retEnhancedInstanceSkyWalkingDynamicField); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerConstructorV412InterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerConstructorV412InterceptorTest.java new file mode 100644 index 0000000000..a87a4e4979 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerConstructorV412InterceptorTest.java @@ -0,0 +1,68 @@ +/* + * 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.spring.cloud.gateway.v412x; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import reactor.netty.http.client.HttpClientConfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class HttpClientFinalizerConstructorV412InterceptorTest { + + private static final String URI = "http://localhost:8080/get"; + private final EnhancedInstance enhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + private HttpClientConfig httpClientConfig; + private HttpClientFinalizerConstructorV412Interceptor httpClientFinalizerConstructorInterceptor; + + @Before + public void setUp() { + httpClientConfig = mock(HttpClientConfig.class); + when(httpClientConfig.uri()).thenReturn(URI); + httpClientFinalizerConstructorInterceptor = new HttpClientFinalizerConstructorV412Interceptor(); + } + + @Test + public void onConstruct() { + httpClientFinalizerConstructorInterceptor.onConstruct(enhancedInstance, new Object[]{httpClientConfig}); + final EnhanceObjectCache enhanceCache = (EnhanceObjectCache) enhancedInstance.getSkyWalkingDynamicField(); + assertNotNull(enhanceCache); + assertEquals(enhanceCache.getUrl(), URI); + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerUriV412InterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerUriV412InterceptorTest.java new file mode 100644 index 0000000000..0cb079b299 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerUriV412InterceptorTest.java @@ -0,0 +1,176 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +@RunWith(TracingSegmentRunner.class) +public class HttpClientFinalizerUriV412InterceptorTest { + + private final static String URI = "http://localhost:8080/get"; + private final static String ENTRY_OPERATION_NAME = "/get"; + private final HttpClientFinalizerUriV412Interceptor uriInterceptor = new HttpClientFinalizerUriV412Interceptor(); + private final EnhancedInstance enhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + private final EnhancedInstance retEnhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + private AbstractSpan entrySpan; + + @Before + public void setUp() throws Exception { + entrySpan = ContextManager.createEntrySpan(ENTRY_OPERATION_NAME, null); + entrySpan.setLayer(SpanLayer.HTTP); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + } + + @Test + public void testWithDynamicFieldNull() throws Throwable { + enhancedInstance.setSkyWalkingDynamicField(null); + retEnhancedInstance.setSkyWalkingDynamicField(null); + uriInterceptor.afterMethod(enhancedInstance, null, null, null, retEnhancedInstance); + assertNull(retEnhancedInstance.getSkyWalkingDynamicField()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + + @Test + public void testWithRetDynamicFieldNotNull() throws Throwable { + enhancedInstance.setSkyWalkingDynamicField(null); + EnhanceObjectCache enhanceObjectCache2 = new EnhanceObjectCache(); + retEnhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache2); + + uriInterceptor.afterMethod(enhancedInstance, null, new Object[]{URI}, null, retEnhancedInstance); + Object retEnhancedInstanceSkyWalkingDynamicField = retEnhancedInstance.getSkyWalkingDynamicField(); + assertNotNull(retEnhancedInstanceSkyWalkingDynamicField); + assertTrue(retEnhancedInstanceSkyWalkingDynamicField instanceof EnhanceObjectCache); + EnhanceObjectCache retEnhanceObjectCache = (EnhanceObjectCache) retEnhancedInstanceSkyWalkingDynamicField; + assertNull(retEnhanceObjectCache.getContextSnapshot()); + assertNotNull(retEnhanceObjectCache.getUrl()); + assertEquals(URI, retEnhanceObjectCache.getUrl()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + + @Test + public void testWithDynamicFieldNotNull() throws Throwable { + ContextSnapshot contextSnapshot = ContextManager.capture(); + EnhanceObjectCache enhanceObjectCache = new EnhanceObjectCache(); + enhanceObjectCache.setContextSnapshot(contextSnapshot); + enhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache); + EnhanceObjectCache enhanceObjectCache2 = new EnhanceObjectCache(); + retEnhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache2); + + uriInterceptor.afterMethod(enhancedInstance, null, new Object[]{URI}, null, retEnhancedInstance); + Object retEnhancedInstanceSkyWalkingDynamicField = retEnhancedInstance.getSkyWalkingDynamicField(); + assertNotNull(retEnhancedInstanceSkyWalkingDynamicField); + assertTrue(retEnhancedInstanceSkyWalkingDynamicField instanceof EnhanceObjectCache); + EnhanceObjectCache retEnhanceObjectCache = (EnhanceObjectCache) retEnhancedInstanceSkyWalkingDynamicField; + assertNotNull(retEnhanceObjectCache.getContextSnapshot()); + assertTrue(contextSnapshot == retEnhanceObjectCache.getContextSnapshot()); + assertNotNull(retEnhanceObjectCache.getUrl()); + assertEquals(URI, retEnhanceObjectCache.getUrl()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + + @Test + public void testWithRetDynamicFieldNull() throws Throwable { + ContextSnapshot contextSnapshot = ContextManager.capture(); + EnhanceObjectCache enhanceObjectCache = new EnhanceObjectCache(); + enhanceObjectCache.setContextSnapshot(contextSnapshot); + enhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache); + retEnhancedInstance.setSkyWalkingDynamicField(null); + + uriInterceptor.afterMethod(enhancedInstance, null, new Object[]{URI}, null, retEnhancedInstance); + Object retEnhancedInstanceSkyWalkingDynamicField = retEnhancedInstance.getSkyWalkingDynamicField(); + assertNull(retEnhancedInstanceSkyWalkingDynamicField); + assertNotNull(enhancedInstance.getSkyWalkingDynamicField()); + assertTrue(enhancedInstance.getSkyWalkingDynamicField() instanceof EnhanceObjectCache); + EnhanceObjectCache objInstObjectCache = (EnhanceObjectCache) enhancedInstance.getSkyWalkingDynamicField(); + assertTrue(contextSnapshot == objInstObjectCache.getContextSnapshot()); + assertNull(objInstObjectCache.getUrl()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerV412InterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerV412InterceptorTest.java new file mode 100644 index 0000000000..8018013db0 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/HttpClientFinalizerV412InterceptorTest.java @@ -0,0 +1,204 @@ +/* + * 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.spring.cloud.gateway.v412x; + +import io.netty.handler.codec.http.HttpResponseStatus; +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.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.reactivestreams.Publisher; +import reactor.core.publisher.Flux; +import reactor.netty.Connection; +import reactor.netty.NettyOutbound; +import reactor.netty.http.client.HttpClientRequest; +import reactor.netty.http.client.HttpClientResponse; + +import java.util.List; +import java.util.function.BiFunction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(TracingSegmentRunner.class) +public class HttpClientFinalizerV412InterceptorTest { + + private final static String URI = "http://localhost:8080/get"; + private final static String ENTRY_OPERATION_NAME = "/get"; + private final HttpClientFinalizerSendV412Interceptor sendInterceptor = new HttpClientFinalizerSendV412Interceptor(); + private final HttpClientFinalizerResponseConnectionV412Interceptor responseConnectionInterceptor = new HttpClientFinalizerResponseConnectionV412Interceptor(); + private final BiFunction> originalSendBiFunction = (httpClientRequest, nettyOutbound) -> (Publisher) s -> { + }; + private final BiFunction> originalResponseConnectionBiFunction = (httpClientResponse, connection) -> (Publisher) s -> { + }; + private final EnhancedInstance enhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + private HttpClientResponse mockResponse; + private HttpClientRequest mockRequest; + @SegmentStoragePoint + private SegmentStorage segmentStorage; + private AbstractSpan entrySpan; + + @Before + public void setUp() throws Exception { + entrySpan = ContextManager.createEntrySpan(ENTRY_OPERATION_NAME, null); + entrySpan.setLayer(SpanLayer.HTTP); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + mockRequest = new MockClientRequest(); + mockResponse = new MockClientResponse(); + final EnhanceObjectCache enhanceObjectCache = new EnhanceObjectCache(); + enhanceObjectCache.setUrl(URI); + enhanceObjectCache.setContextSnapshot(ContextManager.capture()); + enhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache); + } + + @Test + public void testWithDynamicFieldNull() throws Throwable { + enhancedInstance.setSkyWalkingDynamicField(null); + executeSendRequest(); + stopEntrySpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(1, traceSegments.size()); + } + + @Test + public void testWithContextSnapshotNull() throws Throwable { + EnhanceObjectCache objectCache = (EnhanceObjectCache) enhancedInstance.getSkyWalkingDynamicField(); + objectCache.setContextSnapshot(null); + executeSendRequest(); + stopEntrySpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(1, traceSegments.size()); + } + + @Test + public void testWithEmptyUri() throws Throwable { + final EnhanceObjectCache objectCache = (EnhanceObjectCache) enhancedInstance.getSkyWalkingDynamicField(); + objectCache.setUrl(""); + executeSendRequest(); + stopEntrySpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(1, traceSegments.size()); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + assertNotNull(spans); + assertEquals(2, spans.size()); + assertNotNull(spans.get(1)); + assertUpstreamSpan(spans.get(1)); + assertNotNull(spans.get(0)); + assertSendSpan(spans.get(0)); + assertNotNull(objectCache.getSpan1()); + assertEquals(objectCache.getSpan1().getSpanId(), spans.get(0).getSpanId()); + } + + @Test + public void testWithUri() throws Throwable { + executeSendRequest(); + stopEntrySpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(1, traceSegments.size()); + final EnhanceObjectCache objectCache = (EnhanceObjectCache) enhancedInstance + .getSkyWalkingDynamicField(); + assertNotNull(objectCache.getSpan1()); + assertNotNull(objectCache.getSpan()); + assertTrue(objectCache.getSpan().isExit()); + assertEquals(objectCache.getSpan().getOperationName(), "SpringCloudGateway/sendRequest"); + assertEquals(objectCache.getSpan1().getOperationName(), "SpringCloudGateway/send"); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + assertNotNull(spans); + assertEquals(3, spans.size()); + assertUpstreamSpan(spans.get(2)); + assertSendSpan(spans.get(1)); + assertDownstreamSpan(spans.get(0)); + } + + private void executeSendRequest() throws Throwable { + Object[] sendArguments = new Object[]{originalSendBiFunction}; + sendInterceptor.beforeMethod(enhancedInstance, null, sendArguments, null, null); + sendInterceptor.afterMethod(enhancedInstance, null, new Object[0], null, enhancedInstance); + ((BiFunction>) sendArguments[0]) + .apply(mockRequest, null); + Object[] responseConnectionArguments = new Object[]{originalResponseConnectionBiFunction}; + responseConnectionInterceptor + .beforeMethod(enhancedInstance, null, responseConnectionArguments, null, null); + Flux flux = Flux.just(0); + + flux = (Flux) responseConnectionInterceptor.afterMethod(enhancedInstance, null, new Object[0], null, flux); + + ((BiFunction>) responseConnectionArguments[0]) + .apply(mockResponse, null); + flux.blockFirst(); + } + + private void assertUpstreamSpan(AbstractSpan span) { + SpanAssert.assertLayer(span, SpanLayer.HTTP); + SpanAssert.assertComponent(span, ComponentsDefine.SPRING_WEBFLUX); + } + + private void assertSendSpan(AbstractSpan span) { + SpanAssert.assertComponent(span, ComponentsDefine.SPRING_CLOUD_GATEWAY); + assertEquals(span.getOperationName(), "SpringCloudGateway/send"); + } + + private void assertDownstreamSpan(AbstractSpan span) { + SpanAssert.assertLayer(span, SpanLayer.HTTP); + SpanAssert.assertComponent(span, ComponentsDefine.SPRING_CLOUD_GATEWAY); + SpanAssert.assertTagSize(span, 2); + SpanAssert.assertTag(span, 0, URI); + SpanAssert.assertTag(span, 1, String.valueOf(HttpResponseStatus.OK.code())); + } + + private void stopEntrySpan() { + if (ContextManager.isActive() && ContextManager.activeSpan() == entrySpan) { + ContextManager.stopSpan(entrySpan); + } + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/MockClientRequest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/MockClientRequest.java new file mode 100644 index 0000000000..ad357e3e29 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/MockClientRequest.java @@ -0,0 +1,135 @@ +/* + * 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.spring.cloud.gateway.v412x; + +import io.netty.handler.codec.http.DefaultHttpHeaders; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.cookie.Cookie; +import reactor.netty.http.client.HttpClientRequest; +import reactor.util.context.Context; +import reactor.util.context.ContextView; + +import java.time.Duration; +import java.util.Map; +import java.util.Set; + +public class MockClientRequest implements HttpClientRequest { + + @Override + public HttpClientRequest addCookie(Cookie cookie) { + return null; + } + + @Override + public HttpClientRequest addHeader(CharSequence charSequence, CharSequence charSequence1) { + return null; + } + + @Override + public HttpClientRequest header(CharSequence charSequence, CharSequence charSequence1) { + return null; + } + + @Override + public HttpClientRequest headers(HttpHeaders httpHeaders) { + return null; + } + + @Override + public boolean isFollowRedirect() { + return false; + } + + @Override + public HttpClientRequest responseTimeout(Duration duration) { + return null; + } + + @Override + public Context currentContext() { + return null; + } + + @Override + public ContextView currentContextView() { + return null; + } + + @Override + public String[] redirectedFrom() { + return new String[0]; + } + + @Override + public HttpHeaders requestHeaders() { + return new DefaultHttpHeaders(); + } + + @Override + public String resourceUrl() { + return null; + } + + @Override + public Map> cookies() { + return null; + } + + @Override + public boolean isKeepAlive() { + return false; + } + + @Override + public boolean isWebsocket() { + return false; + } + + @Override + public HttpMethod method() { + return null; + } + + @Override + public String path() { + return HttpClientRequest.super.path(); + } + + @Override + public String fullPath() { + return null; + } + + @Override + public String requestId() { + return null; + } + + @Override + public String uri() { + return null; + } + + @Override + public HttpVersion version() { + return null; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/MockClientResponse.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/MockClientResponse.java new file mode 100644 index 0000000000..a2381d0b15 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/MockClientResponse.java @@ -0,0 +1,120 @@ +/* + * 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.spring.cloud.gateway.v412x; + +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.cookie.Cookie; +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClientResponse; +import reactor.util.context.Context; +import reactor.util.context.ContextView; + +import java.util.Map; +import java.util.Set; + +public class MockClientResponse implements HttpClientResponse { + + @Override + public HttpHeaders responseHeaders() { + return null; + } + + @Override + public HttpResponseStatus status() { + return HttpResponseStatus.OK; + } + + @Override + public Mono trailerHeaders() { + return null; + } + + @Override + public Context currentContext() { + return null; + } + + @Override + public ContextView currentContextView() { + return null; + } + + @Override + public String[] redirectedFrom() { + return new String[0]; + } + + @Override + public HttpHeaders requestHeaders() { + return null; + } + + @Override + public String resourceUrl() { + return null; + } + + @Override + public Map> cookies() { + return null; + } + + @Override + public boolean isKeepAlive() { + return false; + } + + @Override + public boolean isWebsocket() { + return false; + } + + @Override + public HttpMethod method() { + return null; + } + + @Override + public String path() { + return HttpClientResponse.super.path(); + } + + @Override + public String fullPath() { + return null; + } + + @Override + public String requestId() { + return null; + } + + @Override + public String uri() { + return null; + } + + @Override + public HttpVersion version() { + return null; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingFilterV412InterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingFilterV412InterceptorTest.java new file mode 100644 index 0000000000..75232fcc1c --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingFilterV412InterceptorTest.java @@ -0,0 +1,222 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.springframework.context.ApplicationContext; +import org.springframework.context.i18n.LocaleContext; +import org.springframework.http.codec.multipart.Part; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.util.MultiValueMap; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebSession; +import reactor.core.publisher.Mono; + +import java.security.Principal; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +@RunWith(TracingSegmentRunner.class) +public class NettyRoutingFilterV412InterceptorTest { + private static class ServerWebExchangeEnhancedInstance implements ServerWebExchange, EnhancedInstance { + private ContextSnapshot snapshot; + Map attributes = new HashMap<>(); + + @Override + public Object getSkyWalkingDynamicField() { + return snapshot; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.snapshot = (ContextSnapshot) value; + } + + @Override + public ServerHttpRequest getRequest() { + return null; + } + + @Override + public ServerHttpResponse getResponse() { + return null; + } + + @Override + public Map getAttributes() { + return attributes; + } + + @Override + public Mono getSession() { + return null; + } + + @Override + public Mono getPrincipal() { + return null; + } + + @Override + public Mono> getFormData() { + return null; + } + + @Override + public Mono> getMultipartData() { + return null; + } + + @Override + public LocaleContext getLocaleContext() { + return null; + } + + @Override + public ApplicationContext getApplicationContext() { + return null; + } + + @Override + public boolean isNotModified() { + return false; + } + + @Override + public boolean checkNotModified(Instant instant) { + return false; + } + + @Override + public boolean checkNotModified(String s) { + return false; + } + + @Override + public boolean checkNotModified(String s, Instant instant) { + return false; + } + + @Override + public String transformUrl(String s) { + return null; + } + + @Override + public void addUrlTransformer(Function function) { + + } + + @Override + public String getLogPrefix() { + return null; + } + } + + private final ServerWebExchangeEnhancedInstance enhancedInstance = new ServerWebExchangeEnhancedInstance(); + private final NettyRoutingFilterV412Interceptor interceptor = new NettyRoutingFilterV412Interceptor(); + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Before + public void setUp() throws Exception { + } + + @Test + public void testWithNullDynamicField() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(1, spans.size()); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + } + + @Test + public void testWithContextSnapshot() throws Throwable { + final AbstractSpan entrySpan = ContextManager.createEntrySpan("/get", null); + SpanLayer.asHttp(entrySpan); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + enhancedInstance.setSkyWalkingDynamicField(ContextManager.capture()); + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + ContextManager.stopSpan(entrySpan); + final List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + Assert.assertNotNull(spans); + Assert.assertEquals(spans.size(), 2); + SpanAssert.assertComponent(spans.get(0), ComponentsDefine.SPRING_CLOUD_GATEWAY); + SpanAssert.assertComponent(spans.get(1), ComponentsDefine.SPRING_WEBFLUX); + SpanAssert.assertLayer(spans.get(1), SpanLayer.HTTP); + } + + private static final String NETTY_ROUTING_FILTER_TRACED_ATTR = + NettyRoutingFilterV412Interceptor.class.getName() + ".isTraced"; + + @Test + public void testIsTraced() throws Throwable { + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + Assert.assertEquals(enhancedInstance.getAttributes().get(NETTY_ROUTING_FILTER_TRACED_ATTR), true); + Assert.assertFalse(ContextManager.isActive()); + + // no more need this, span was stopped at interceptor#afterMethod + // ContextManager.stopSpan(); + + interceptor.beforeMethod(null, null, new Object[]{enhancedInstance}, null, null); + interceptor.afterMethod(null, null, null, null, null); + Assert.assertEquals(enhancedInstance.getAttributes().get(NETTY_ROUTING_FILTER_TRACED_ATTR), true); + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingGetHttpClientV412InterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingGetHttpClientV412InterceptorTest.java new file mode 100644 index 0000000000..5f3f8811ae --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v412x/NettyRoutingGetHttpClientV412InterceptorTest.java @@ -0,0 +1,115 @@ +/* + * 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.spring.cloud.gateway.v412x; + +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.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v4x.define.EnhanceObjectCache; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +@RunWith(TracingSegmentRunner.class) +public class NettyRoutingGetHttpClientV412InterceptorTest { + private final static String ENTRY_OPERATION_NAME = "/get"; + private final NettyRoutingGetHttpClientV412Interceptor interceptor = new NettyRoutingGetHttpClientV412Interceptor(); + private final EnhancedInstance enhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + private final EnhancedInstance retEnhancedInstance = new EnhancedInstance() { + private EnhanceObjectCache enhanceObjectCache; + @Override + public Object getSkyWalkingDynamicField() { + return enhanceObjectCache; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.enhanceObjectCache = (EnhanceObjectCache) value; + } + }; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + private AbstractSpan entrySpan; + + @Before + public void setUp() throws Exception { + } + + @Test + public void testWithContextIsActive() throws Throwable { + entrySpan = ContextManager.createEntrySpan(ENTRY_OPERATION_NAME, null); + entrySpan.setLayer(SpanLayer.HTTP); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + interceptor.afterMethod(enhancedInstance, null, null, null, retEnhancedInstance); + assertNotNull(retEnhancedInstance.getSkyWalkingDynamicField()); + assertTrue(retEnhancedInstance.getSkyWalkingDynamicField() instanceof EnhanceObjectCache); + EnhanceObjectCache enhanceObjectCache = (EnhanceObjectCache) retEnhancedInstance.getSkyWalkingDynamicField(); + assertNotNull(enhanceObjectCache.getContextSnapshot()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + + @Test + public void testWithContextNotActive() throws Throwable { + interceptor.afterMethod(enhancedInstance, null, null, null, retEnhancedInstance); + assertNull(retEnhancedInstance.getSkyWalkingDynamicField()); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } +} diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-4.1.2.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..fe66b460d6 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/config/expectedData.yaml @@ -0,0 +1,155 @@ +# 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: gateway-projectB-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: /provider/timeout/error + parentSpanId: 0 + spanId: 1 + isError: true + spanType: Exit + tags: + - { key: url, value: not null } + - { key: http.method, value: GET } + - { key: http.status_code, value: '500' } + logs: + - logEvent: + - { key: event, value: error } + - { key: error.kind, value: not null } + - { key: message, value: not null } + - {key: stack, value: not null} + - logEvent: + - { key: event, value: error } + - { key: error.kind, value: not null } + - { key: message, value: not null } + - { key: stack, value: not null } + - operationName: GET:/provider/b/testcase + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: not null} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: SpringCloudGateway/send, networkAddress: 'localhost:18070', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' +- serviceName: gateway-projectA-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: /provider/timeout/error + parentSpanId: -1 + spanId: 0 + spanLayer: Http + isError: true + spanType: Entry + tags: + - {key: url, value: 'http://localhost:8080/provider/timeout/error' } + - {key: http.method, value: GET} + - {key: http.status_code, value: '500'} + - segmentId: not null + spans: + - operationName: SpringCloudGateway/sendRequest + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 61 + isError: true + spanType: Exit + peer: 1.2.3.4:18070 + skipAnalysis: false + tags: + - { key: url, value: not null } + logs: + - logEvent: + - { key: event, value: error } + - { key: error.kind, value: not null } + - { key: message, value: not null } + - { key: stack, value: not null} + - operationName: SpringCloudGateway/send + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + spanType: Local + refs: + - { parentEndpoint: 'SpringCloudGateway/GatewayFilter', networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: SpringCloudGateway/sendRequest + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 61 + isError: false + spanType: Exit + peer: 'localhost:18070' + tags: + - {key: url, value: not null} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: SpringCloudGateway/send + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: 'SpringCloudGateway/GatewayFilter', networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: /provider/b/testcase + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 67 + isError: false + spanType: Entry + peer: not null + tags: + - { key: url, value: 'http://localhost:8080/provider/b/testcase' } + - { key: http.method, value: GET } + - { key: http.status_code, value: '200' } + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/configuration.yml b/test/plugin/scenarios/gateway-4.1.2.x-scenario/configuration.yml new file mode 100644 index 0000000000..a958b8d680 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-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/provider/b/testcase +healthCheck: http://localhost:8080/provider/b/healthCheck +startScript: ./bin/startup.sh +runningMode: with_optional +withPlugins: apm-spring-cloud-gateway-4.x-plugin-*.jar diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/bin/startup.sh b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/bin/startup.sh new file mode 100644 index 0000000000..0d28675632 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/bin/startup.sh @@ -0,0 +1,24 @@ +#!/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} "-Dskywalking.agent.service_name=gateway-projectA-scenario" ${home}/../libs/gateway-projectA-scenario.jar & +sleep 1 + +java -jar ${agent_opts} "-Dskywalking.agent.service_name=gateway-projectB-scenario" ${home}/../libs/gateway-projectB-scenario.jar & diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/pom.xml b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/pom.xml new file mode 100644 index 0000000000..8e7d699cd7 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/pom.xml @@ -0,0 +1,54 @@ + + + + + org.apache.skywalking + gateway-4.1.2.x-scenario + 5.0.0 + + 4.0.0 + + gateway-dist + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ../target/ + + + + + + + diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/src/main/assembly/assembly.xml b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..00d04e28e0 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-dist/src/main/assembly/assembly.xml @@ -0,0 +1,46 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ../gateway-projectA-scenario/target/gateway-projectA-scenario.jar + ./libs + 0775 + + + ../gateway-projectB-scenario/target/gateway-projectB-scenario.jar + ./libs + 0775 + + + \ No newline at end of file diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/pom.xml b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/pom.xml new file mode 100644 index 0000000000..ad7b0f6f9b --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/pom.xml @@ -0,0 +1,56 @@ + + + + + org.apache.skywalking + gateway-4.1.2.x-scenario + 5.0.0 + + 4.0.0 + + gateway-projectA-scenario + + + + org.springframework.cloud + spring-cloud-starter-gateway + ${test.framework.version} + + + + + gateway-projectA-scenario + + + org.springframework.boot + spring-boot-maven-plugin + 3.0.0 + + + + repackage + + + + + + + diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java new file mode 100644 index 0000000000..40517d1d3f --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java @@ -0,0 +1,31 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +@Component +public class ApiKeyResolver implements KeyResolver { + + public Mono resolve(ServerWebExchange exchange) { + return Mono.just(exchange.getRequest().getPath().value()); + } +} diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java new file mode 100644 index 0000000000..68eb95b0c6 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java @@ -0,0 +1,29 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java new file mode 100644 index 0000000000..af891eae20 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java @@ -0,0 +1,38 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +public class Test1Filter implements GlobalFilter, Ordered { + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest buildRequest = exchange.getRequest().mutate().build(); + return chain.filter(exchange.mutate().request(buildRequest).build()); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java new file mode 100644 index 0000000000..d3a5846bd5 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java @@ -0,0 +1,39 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +public class Test2Filter implements GlobalFilter, Ordered { + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest buildRequest = exchange.getRequest().mutate().build(); + return chain.filter(exchange.mutate().request(buildRequest).build()); + } + + @Override + public int getOrder() { + return 1; + } +} diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java new file mode 100644 index 0000000000..29f9627bdf --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java @@ -0,0 +1,35 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class TestFilterConfig { + + @Bean + public Test1Filter test1Filter() { + return new Test1Filter(); + } + + @Bean + public Test2Filter test2Filter() { + return new Test2Filter(); + } +} diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml new file mode 100644 index 0000000000..7639e7ce8a --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml @@ -0,0 +1,33 @@ +# +# 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 +spring: + cloud: + gateway: + httpclient: + connect-timeout: 2000 + routes: + - id: provider_route + uri: http://localhost:18070 + predicates: + - Path=/provider/b/* + - id: provider_timeout + uri: http://1.2.3.4:18070 + predicates: + - Path=/provider/timeout/* diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/pom.xml b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/pom.xml new file mode 100644 index 0000000000..6669207a94 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/pom.xml @@ -0,0 +1,57 @@ + + + + + gateway-4.1.2.x-scenario + org.apache.skywalking + 5.0.0 + + 4.0.0 + + gateway-projectB-scenario + + + + org.springframework.boot + spring-boot-starter-web + 2.1.0.RELEASE + + + + + gateway-projectB-scenario + + + org.springframework.boot + spring-boot-maven-plugin + 1.5.9.RELEASE + + + + repackage + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java new file mode 100644 index 0000000000..51c94655c7 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java @@ -0,0 +1,31 @@ +/* + * 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.sc.gateway.projectB; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(value = {"test.apache.skywalking.apm.testcase.sc.gateway.projectB.controller"}) +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java new file mode 100644 index 0000000000..923d7fd7ff --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java @@ -0,0 +1,40 @@ +/* + * 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.sc.gateway.projectB.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +@RestController +public class TestController { + + @RequestMapping("/provider/b/testcase") + public String testcase() { + try { + new RestTemplate().getForEntity("http://localhost:8080/provider/timeout/error", String.class); + } catch (Exception e) { + } + return "1"; + } + + @RequestMapping("/provider/b/healthCheck") + public String healthCheck() { + return "Success"; + } +} diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties new file mode 100644 index 0000000000..cac2c4d5a1 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties @@ -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. +# +server.port=18070 \ No newline at end of file diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/pom.xml b/test/plugin/scenarios/gateway-4.1.2.x-scenario/pom.xml new file mode 100644 index 0000000000..41b9e64c15 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/pom.xml @@ -0,0 +1,59 @@ + + + + 4.0.0 + + org.apache.skywalking + gateway-4.1.2.x-scenario + pom + 5.0.0 + + gateway-projectA-scenario + gateway-projectB-scenario + gateway-dist + + + skywalking-gateway-4.1.2.x-scenario + + + UTF-8 + 1.8 + 3.8.1 + 4.1.2 + ${test.framework.version} + + + + gateway-4.1.2.x-scenario + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + + + diff --git a/test/plugin/scenarios/gateway-4.1.2.x-scenario/support-version.list b/test/plugin/scenarios/gateway-4.1.2.x-scenario/support-version.list new file mode 100644 index 0000000000..347dda15d0 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.1.2.x-scenario/support-version.list @@ -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. + +4.1.2 +4.1.6 +4.2.0 \ No newline at end of file diff --git a/test/plugin/scenarios/gateway-4.x-scenario/support-version.list b/test/plugin/scenarios/gateway-4.x-scenario/support-version.list index ff90e11c58..d69db104f9 100644 --- a/test/plugin/scenarios/gateway-4.x-scenario/support-version.list +++ b/test/plugin/scenarios/gateway-4.x-scenario/support-version.list @@ -16,4 +16,5 @@ 4.0.0 4.0.8 -4.1.0 \ No newline at end of file +4.1.0 +4.1.1 \ No newline at end of file From affbaa8bfd3331e358ac5a58e4e286f464baca74 Mon Sep 17 00:00:00 2001 From: jiangyuan Date: Sun, 19 Jan 2025 18:44:47 +0800 Subject: [PATCH 054/114] Fix ConsumeDriver running status (#748) --- CHANGES.md | 1 + .../commons/datacarrier/consumer/ConsumeDriver.java | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 4fd1859d4c..2a797ed4cc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -28,6 +28,7 @@ Release Notes. * Add Caffeine plugin as optional. * Add Undertow 2.1.7.final+ worker thread pool metrics. * Support for tracking in spring gateway versions 4.1.2 and above. +* Fix `ConsumeDriver` running status concurrency issues. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) diff --git a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumeDriver.java b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumeDriver.java index a6d808fead..853c7fc3bc 100644 --- a/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumeDriver.java +++ b/apm-commons/apm-datacarrier/src/main/java/org/apache/skywalking/apm/commons/datacarrier/consumer/ConsumeDriver.java @@ -27,7 +27,7 @@ * Pool of consumers

Created by wusheng on 2016/10/25. */ public class ConsumeDriver implements IDriver { - private boolean running; + private volatile boolean running; private ConsumerThread[] consumerThreads; private Channels channels; private ReentrantLock lock; @@ -88,6 +88,9 @@ public void begin(Channels channels) { } lock.lock(); try { + if (running) { + return; + } this.allocateBuffer2Thread(); for (ConsumerThread consumerThread : consumerThreads) { consumerThread.start(); @@ -124,8 +127,14 @@ private void allocateBuffer2Thread() { @Override public void close(Channels channels) { + if (!running) { + return; + } lock.lock(); try { + if (!running) { + return; + } this.running = false; for (ConsumerThread consumerThread : consumerThreads) { consumerThread.shutdown(); From 4183bac83b7a1bd40edec36ef212a36eadf323f5 Mon Sep 17 00:00:00 2001 From: wangcanfeng Date: Fri, 24 Jan 2025 12:54:56 +0800 Subject: [PATCH 055/114] Polish URLParserTest.java as tested method is static. (#749) Don't need to create an instance to verify static method. --- .../connectionurl/parser/URLParserTest.java | 96 +++++++++---------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java index 48715ad840..2a0e87e315 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java @@ -27,7 +27,7 @@ public class URLParserTest { @Test public void testParseMysqlJDBCURLWithHost() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost/test"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:mysql//primaryhost/test"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("test")); assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3306")); @@ -35,7 +35,7 @@ public void testParseMysqlJDBCURLWithHost() { @Test public void testParseMysqlJDBCURLWithoutDB() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost?profileSQL=true"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:mysql//primaryhost?profileSQL=true"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("")); assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3306")); @@ -43,7 +43,7 @@ public void testParseMysqlJDBCURLWithoutDB() { @Test public void testParseMysqlJDBCURLWithHostAndPort() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost:3307/test?profileSQL=true"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:mysql//primaryhost:3307/test?profileSQL=true"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("test")); assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3307")); @@ -51,7 +51,7 @@ public void testParseMysqlJDBCURLWithHostAndPort() { @Test public void testParseMysqlJDBCURLWithMultiHost() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost:3307,secondaryhost1,secondaryhost2/test?profileSQL=true"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:mysql//primaryhost:3307,secondaryhost1,secondaryhost2/test?profileSQL=true"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("test")); assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3307,secondaryhost1:3306,secondaryhost2:3306")); @@ -59,7 +59,7 @@ public void testParseMysqlJDBCURLWithMultiHost() { @Test public void testParseMysqlJDBCURLWitOutDatabase() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost:3307?profileSQL=true"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:mysql//primaryhost:3307?profileSQL=true"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("")); assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3307")); @@ -67,7 +67,7 @@ public void testParseMysqlJDBCURLWitOutDatabase() { @Test public void testParseMysqlJDBCURLWithConnectorJs() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql:replication://master,slave1,slave2,slave3/test"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:mysql:replication://master,slave1,slave2,slave3/test"); assertThat(connectionInfo.getDBType(), is("Mysql")); assertThat(connectionInfo.getDatabaseName(), is("test")); assertThat(connectionInfo.getDatabasePeer(), is("master:3306,slave1:3306,slave2:3306,slave3:3306")); @@ -75,7 +75,7 @@ public void testParseMysqlJDBCURLWithConnectorJs() { @Test public void testParseOracleJDBCURLWithHost() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@localhost:orcl"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:oracle:thin:@localhost:orcl"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:1521")); @@ -83,7 +83,7 @@ public void testParseOracleJDBCURLWithHost() { @Test public void testParseOracleJDBCURLWithHostAndPort() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@localhost:1522:orcl"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:oracle:thin:@localhost:1522:orcl"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:1522")); @@ -91,7 +91,7 @@ public void testParseOracleJDBCURLWithHostAndPort() { @Test public void testParseOracleSID() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@localhost:1522/orcl"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:oracle:thin:@localhost:1522/orcl"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:1522")); @@ -99,7 +99,7 @@ public void testParseOracleSID() { @Test public void testParseOracleServiceName() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@//localhost:1531/orcl"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:oracle:thin:@//localhost:1531/orcl"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:1531")); @@ -107,7 +107,7 @@ public void testParseOracleServiceName() { @Test public void testParseOracleTNSName() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST= localhost )(PORT= 1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)))"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST= localhost )(PORT= 1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)))"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:1521")); @@ -115,7 +115,7 @@ public void testParseOracleTNSName() { @Test public void testParseOracleLowerTNSName() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@(description=(address=(protocol=tcp)(host= localhost )(port= 1521))(connect_data=(server=dedicated)(service_name=orcl)))"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:oracle:thin:@(description=(address=(protocol=tcp)(host= localhost )(port= 1521))(connect_data=(server=dedicated)(service_name=orcl)))"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:1521")); @@ -123,7 +123,7 @@ public void testParseOracleLowerTNSName() { @Test public void testParseOracleTNSNameWithMultiAddress() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL= TCP)(HOST=hostA)(PORT= 1523 ))(ADDRESS=(PROTOCOL=TCP)(HOST=hostB)(PORT= 1521 )))(SOURCE_ROUTE=yes)(CONNECT_DATA=(SERVICE_NAME=orcl)))"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL= TCP)(HOST=hostA)(PORT= 1523 ))(ADDRESS=(PROTOCOL=TCP)(HOST=hostB)(PORT= 1521 )))(SOURCE_ROUTE=yes)(CONNECT_DATA=(SERVICE_NAME=orcl)))"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); assertThat(connectionInfo.getDatabasePeer(), is("hostA:1523,hostB:1521")); @@ -131,7 +131,7 @@ public void testParseOracleTNSNameWithMultiAddress() { @Test public void testParseOracleJDBCURLWithUserNameAndPassword() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:scott/tiger@myhost:1521:orcl"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:oracle:thin:scott/tiger@myhost:1521:orcl"); assertThat(connectionInfo.getDBType(), is("Oracle")); assertThat(connectionInfo.getDatabaseName(), is("orcl")); assertThat(connectionInfo.getDatabasePeer(), is("myhost:1521")); @@ -139,7 +139,7 @@ public void testParseOracleJDBCURLWithUserNameAndPassword() { @Test public void testParseH2JDBCURLWithEmbedded() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:file:/data/sample"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:h2:file:/data/sample"); assertThat(connectionInfo.getDBType(), is("H2")); assertThat(connectionInfo.getDatabaseName(), is("/data/sample")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); @@ -147,7 +147,7 @@ public void testParseH2JDBCURLWithEmbedded() { @Test public void testParseH2JDBCURLWithEmbeddedRunningInWindows() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:file:C:/data/sample"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:h2:file:C:/data/sample"); assertThat(connectionInfo.getDBType(), is("H2")); assertThat(connectionInfo.getDatabaseName(), is("C:/data/sample")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); @@ -155,7 +155,7 @@ public void testParseH2JDBCURLWithEmbeddedRunningInWindows() { @Test public void testParseH2JDBCURLWithMemoryMode() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:mem:test_mem"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:h2:mem:test_mem"); assertThat(connectionInfo.getDBType(), is("H2")); assertThat(connectionInfo.getDatabaseName(), is("test_mem")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:-1")); @@ -163,7 +163,7 @@ public void testParseH2JDBCURLWithMemoryMode() { @Test public void testParseH2JDBCURL() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:tcp://localhost:8084/~/sample"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:h2:tcp://localhost:8084/~/sample"); assertThat(connectionInfo.getDBType(), is("H2")); assertThat(connectionInfo.getDatabaseName(), is("sample")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:8084")); @@ -171,7 +171,7 @@ public void testParseH2JDBCURL() { @Test public void testParseMariadbJDBCURLWithHost() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mariadb//primaryhost/test"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:mariadb//primaryhost/test"); assertThat(connectionInfo.getDBType(), is("Mariadb")); assertThat(connectionInfo.getDatabaseName(), is("test")); assertThat(connectionInfo.getDatabasePeer(), is("primaryhost:3306")); @@ -179,7 +179,7 @@ public void testParseMariadbJDBCURLWithHost() { @Test public void testParseClickhouseJDBCURL() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:clickhouse://localhost:8123/test"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:clickhouse://localhost:8123/test"); assertThat(connectionInfo.getDBType(), is("ClickHouse")); assertThat(connectionInfo.getDatabaseName(), is("test")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:8123")); @@ -187,7 +187,7 @@ public void testParseClickhouseJDBCURL() { @Test public void testParseImpalaJDBCURL() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:impala://localhost:21050/test;AuthMech=3;UID=UserName;PWD=Password"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:impala://localhost:21050/test;AuthMech=3;UID=UserName;PWD=Password"); assertThat(connectionInfo.getDBType(), is("Impala")); assertThat(connectionInfo.getDatabaseName(), is("test")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:21050")); @@ -195,7 +195,7 @@ public void testParseImpalaJDBCURL() { @Test public void testParseImpalaJDBCURLWithSchema() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:impala://localhost:21050/test"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:impala://localhost:21050/test"); assertThat(connectionInfo.getDBType(), is("Impala")); assertThat(connectionInfo.getDatabaseName(), is("test")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:21050")); @@ -203,14 +203,14 @@ public void testParseImpalaJDBCURLWithSchema() { @Test public void testParseImpalaJDBCURLWithoutSchema() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:impala://localhost:21050"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:impala://localhost:21050"); assertThat(connectionInfo.getDBType(), is("Impala")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:21050")); } @Test public void testParsePostgresqlJDBCURLWithHostAndParams() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:postgresql://localhost:5432/testdb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&allowMultiQueries=true"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:postgresql://localhost:5432/testdb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&allowMultiQueries=true"); assertThat(connectionInfo.getDBType(), is("PostgreSQL")); assertThat(connectionInfo.getDatabaseName(), is("testdb")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:5432")); @@ -218,7 +218,7 @@ public void testParsePostgresqlJDBCURLWithHostAndParams() { @Test public void testParsePostgresqlJDBCURLWithMultiHost() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:postgresql://localhost1:5432,localhost2:5433/testdb?target_session_attrs=any&application_name=myapp"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:postgresql://localhost1:5432,localhost2:5433/testdb?target_session_attrs=any&application_name=myapp"); assertThat(connectionInfo.getDBType(), is("PostgreSQL")); assertThat(connectionInfo.getDatabaseName(), is("testdb")); assertThat(connectionInfo.getDatabasePeer(), is("localhost1:5432,localhost2:5433")); @@ -226,7 +226,7 @@ public void testParsePostgresqlJDBCURLWithMultiHost() { @Test public void testParsePostgresqlJDBCURLWithHostNoPort() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:postgresql://localhost/testdb"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:postgresql://localhost/testdb"); assertThat(connectionInfo.getDBType(), is("PostgreSQL")); assertThat(connectionInfo.getDatabaseName(), is("testdb")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:5432")); @@ -234,7 +234,7 @@ public void testParsePostgresqlJDBCURLWithHostNoPort() { @Test public void testParsePostgresqlJDBCURLWithHostNoDb() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:postgresql://localhost:5432"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:postgresql://localhost:5432"); assertThat(connectionInfo.getDBType(), is("PostgreSQL")); assertThat(connectionInfo.getDatabaseName(), is("")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:5432")); @@ -242,7 +242,7 @@ public void testParsePostgresqlJDBCURLWithHostNoDb() { @Test public void testParsePostgresqlJDBCURLWithHostNoPortAndDb() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:postgresql://localhost"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:postgresql://localhost"); assertThat(connectionInfo.getDBType(), is("PostgreSQL")); assertThat(connectionInfo.getDatabaseName(), is("")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:5432")); @@ -250,7 +250,7 @@ public void testParsePostgresqlJDBCURLWithHostNoPortAndDb() { @Test public void testParsePostgresqlJDBCURLEmpty() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:postgresql://"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:postgresql://"); assertThat(connectionInfo.getDBType(), is("PostgreSQL")); assertThat(connectionInfo.getDatabaseName(), is("")); assertThat(connectionInfo.getDatabasePeer(), is(":5432")); @@ -258,7 +258,7 @@ public void testParsePostgresqlJDBCURLEmpty() { @Test public void testParsePostgresqlJDBCURLWithNamedParams() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:postgresql:///testdb?host=localhost&port=5433"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:postgresql:///testdb?host=localhost&port=5433"); assertThat(connectionInfo.getDBType(), is("PostgreSQL")); assertThat(connectionInfo.getDatabaseName(), is("testdb")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:5433")); @@ -266,7 +266,7 @@ public void testParsePostgresqlJDBCURLWithNamedParams() { @Test public void testParsePostgresqlJDBCURLWithSingleIpv6() { - ConnectionInfo connectionInfo = new URLParser().parser("jdbc:postgresql://[2001:db8::1234]/testdb"); + ConnectionInfo connectionInfo = URLParser.parser("jdbc:postgresql://[2001:db8::1234]/testdb"); assertThat(connectionInfo.getDBType(), is("PostgreSQL")); assertThat(connectionInfo.getDatabaseName(), is("testdb")); assertThat(connectionInfo.getDatabasePeer(), is("[2001:db8::1234]:5432")); @@ -274,7 +274,7 @@ public void testParsePostgresqlJDBCURLWithSingleIpv6() { @Test public void testParsePostgresqlJDBCURLWithMultiIpv6() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:postgresql://[2001:db8::1234],[2001:db8::1235]/testdb"); assertThat(connectionInfo.getDBType(), is("PostgreSQL")); assertThat(connectionInfo.getDatabaseName(), is("testdb")); @@ -283,7 +283,7 @@ public void testParsePostgresqlJDBCURLWithMultiIpv6() { @Test public void testParseOceanBaseJDBCURL() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:oceanbase://localhost:2881/mydb?user=root@sys&password=pass&pool=false&useBulkStmts=true&rewriteBatchedStatements=false&useServerPrepStmts=true"); assertThat(connectionInfo.getDBType(), is("OceanBase")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -292,7 +292,7 @@ public void testParseOceanBaseJDBCURL() { @Test public void testParseOceanBaseJDBCURLWithMultiHosts() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:oceanbase://primaryhost:2888,secondaryhost1,secondaryhost2/mydb?user=root@sys&password=pass&pool=false&useBulkStmts=true&rewriteBatchedStatements=false&useServerPrepStmts=true"); assertThat(connectionInfo.getDBType(), is("OceanBase")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -301,7 +301,7 @@ public void testParseOceanBaseJDBCURLWithMultiHosts() { @Test public void testParseDerbyJDBCURLWithDirMode() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:derby:directory:mydb"); assertThat(connectionInfo.getDBType(), is("Derby")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -310,7 +310,7 @@ public void testParseDerbyJDBCURLWithDirMode() { @Test public void testParseDerbyJDBCURLWithMemMode() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:derby:memory:mydb;create=true"); assertThat(connectionInfo.getDBType(), is("Derby")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -319,7 +319,7 @@ public void testParseDerbyJDBCURLWithMemMode() { @Test public void testParseDerbyJDBCURLWithClassPathMode() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:derby:classpath:/test/mydb"); assertThat(connectionInfo.getDBType(), is("Derby")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -328,7 +328,7 @@ public void testParseDerbyJDBCURLWithClassPathMode() { @Test public void testParseDerbyJDBCURLWithJarMode() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:derby:jar:(C:/dbs.jar)test/mydb"); assertThat(connectionInfo.getDBType(), is("Derby")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -337,7 +337,7 @@ public void testParseDerbyJDBCURLWithJarMode() { @Test public void testParseDerbyJDBCURLWithEmbeddedMode() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:derby:test/mydb;create=true"); assertThat(connectionInfo.getDBType(), is("Derby")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -346,7 +346,7 @@ public void testParseDerbyJDBCURLWithEmbeddedMode() { @Test public void testParseDerbyJDBCURLWithMemModeAndClientServerMode() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:derby://localhost:1527/memory:/test/mydb;create=true"); assertThat(connectionInfo.getDBType(), is("Derby")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -355,7 +355,7 @@ public void testParseDerbyJDBCURLWithMemModeAndClientServerMode() { @Test public void testParseDerbyJDBCURLWithClientServerMode() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:derby://localhost:1527/mydb;create=true;user=root;password=pass"); assertThat(connectionInfo.getDBType(), is("Derby")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -364,7 +364,7 @@ public void testParseDerbyJDBCURLWithClientServerMode() { @Test public void testParseDB2JDBCURL() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:db2://localhost:50000/mydb:user=root;password=pass"); assertThat(connectionInfo.getDBType(), is("DB2")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -373,7 +373,7 @@ public void testParseDB2JDBCURL() { @Test public void testParseDB2JDBCURLWithoutHost() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:db2:mydb:user=root;password=pass"); assertThat(connectionInfo.getDBType(), is("DB2")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); @@ -382,7 +382,7 @@ public void testParseDB2JDBCURLWithoutHost() { @Test public void testParseSqliteJDBCURL() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:sqlite:C/test/mydb.db"); assertThat(connectionInfo.getDBType(), is("Sqlite")); assertThat(connectionInfo.getDatabaseName(), is("mydb.db")); @@ -391,7 +391,7 @@ public void testParseSqliteJDBCURL() { @Test public void testParseSqliteJDBCURLWithMem() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:sqlite::memory:?jdbc.explicit_readonly=true"); assertThat(connectionInfo.getDBType(), is("Sqlite")); assertThat(connectionInfo.getDatabaseName(), is("")); @@ -400,7 +400,7 @@ public void testParseSqliteJDBCURLWithMem() { @Test public void testParseSqliteJDBCURLWithResource() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:sqlite::resource:org/test/mydb.db"); assertThat(connectionInfo.getDBType(), is("Sqlite")); assertThat(connectionInfo.getDatabaseName(), is("mydb.db")); @@ -409,10 +409,10 @@ public void testParseSqliteJDBCURLWithResource() { @Test public void testParseSybaseJDBCURL() { - ConnectionInfo connectionInfo = new URLParser().parser( + ConnectionInfo connectionInfo = URLParser.parser( "jdbc:sybase:Tds:localhost:5000/mydb?charset=utf-8"); assertThat(connectionInfo.getDBType(), is("Sybase")); assertThat(connectionInfo.getDatabaseName(), is("mydb")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:5000")); } -} \ No newline at end of file +} From 534a80c74c423abbcae548c79052f2b17c5ee68e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Wed, 19 Feb 2025 23:03:01 +0800 Subject: [PATCH 056/114] Release 9.4.0 and prepare 9.5.0 (#750) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [maven-release-plugin] prepare release v9.4.0 * [maven-release-plugin] prepare for next development iteration * Update change logs. --------- Co-authored-by: Wu Sheng <“wu.sheng@foxmail.com”> --- CHANGES.md | 29 ++-------------- .../apm-toolkit-kafka/pom.xml | 2 +- .../apm-toolkit-log4j-1.x/pom.xml | 2 +- .../apm-toolkit-log4j-2.x/pom.xml | 2 +- .../apm-toolkit-logback-1.x/pom.xml | 2 +- .../apm-toolkit-meter/pom.xml | 2 +- .../apm-toolkit-micrometer-1.10/pom.xml | 2 +- .../apm-toolkit-micrometer-registry/pom.xml | 2 +- .../apm-toolkit-opentracing/pom.xml | 2 +- .../apm-toolkit-trace/pom.xml | 2 +- .../apm-toolkit-webflux/pom.xml | 2 +- apm-application-toolkit/pom.xml | 2 +- apm-commons/apm-datacarrier/pom.xml | 2 +- apm-commons/apm-util/pom.xml | 2 +- apm-commons/pom.xml | 2 +- apm-protocol/apm-network/pom.xml | 2 +- apm-protocol/pom.xml | 2 +- apm-sniffer/apm-agent-core/pom.xml | 2 +- apm-sniffer/apm-agent/pom.xml | 2 +- .../activemq-5.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/aerospike-plugin/pom.xml | 2 +- .../apm-armeria-0.84.x-plugin/pom.xml | 2 +- .../apm-armeria-0.85.x-plugin/pom.xml | 2 +- .../apm-armeria-1.0.x-plugin/pom.xml | 2 +- .../apm-armeria-plugins/pom.xml | 2 +- .../asynchttpclient-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/avro-plugin/pom.xml | 2 +- .../baidu-brpc-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/baidu-brpc-plugin/pom.xml | 2 +- .../apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/canal-1.x-plugin/pom.xml | 2 +- .../cassandra-java-driver-3.x-plugin/pom.xml | 2 +- .../clickhouse-0.3.1-plugin/pom.xml | 2 +- .../clickhouse-0.3.2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/cxf-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/dbcp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/druid-1.x-plugin/pom.xml | 2 +- .../dubbo-2.7.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml | 2 +- .../dubbo-3.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-3.x-plugin/pom.xml | 2 +- .../dubbo-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-plugin/pom.xml | 2 +- .../elastic-job-2.x-plugin/pom.xml | 2 +- .../elasticjob-3.x-plugin/pom.xml | 2 +- .../elasticsearch-5.x-plugin/pom.xml | 2 +- .../elasticsearch-6.x-plugin/pom.xml | 2 +- .../elasticsearch-7.x-plugin/pom.xml | 2 +- .../elasticsearch-common/pom.xml | 2 +- .../feign-default-http-9.x-plugin/pom.xml | 2 +- .../finagle-6.25.x-plugin/pom.xml | 2 +- .../graphql-12.x-15.x-plugin/pom.xml | 2 +- .../graphql-16plus-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-8.x-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/graphql-plugin/pom.xml | 2 +- .../grizzly-2.3.x-4.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/grpc-1.x-plugin/pom.xml | 2 +- .../guava-eventbus-plugin/pom.xml | 2 +- .../apm-sdk-plugin/h2-1.x-plugin/pom.xml | 2 +- .../hbase-1.x-2.x-plugin/pom.xml | 2 +- .../hikaricp-3.x-4.x-plugin/pom.xml | 2 +- .../httpClient-4.x-plugin/pom.xml | 2 +- .../httpasyncclient-4.x-plugin/pom.xml | 2 +- .../httpclient-3.x-plugin/pom.xml | 2 +- .../httpclient-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/httpclient-commons/pom.xml | 2 +- .../hutool-http-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/hutool-plugins/pom.xml | 2 +- .../apm-sdk-plugin/hystrix-1.x-plugin/pom.xml | 2 +- .../influxdb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jdbc-commons/pom.xml | 2 +- .../jedis-2.x-3.x-plugin/pom.xml | 2 +- .../jedis-plugins/jedis-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jedis-plugins/pom.xml | 2 +- .../apm-sdk-plugin/jersey-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jersey-3.x-plugin/pom.xml | 2 +- .../jetty-client-11.x-plugin/pom.xml | 2 +- .../jetty-client-9.0-plugin/pom.xml | 2 +- .../jetty-client-9.x-plugin/pom.xml | 2 +- .../jetty-server-11.x-plugin/pom.xml | 2 +- .../jetty-server-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jetty-plugin/pom.xml | 2 +- .../jetty-thread-pool-plugin/pom.xml | 2 +- .../jsonrpc4j-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/kafka-commons/pom.xml | 2 +- .../apm-sdk-plugin/kafka-plugin/pom.xml | 2 +- .../kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/lettuce-5.x-plugin/pom.xml | 2 +- .../light4j-plugins/light4j-plugin/pom.xml | 2 +- .../apm-sdk-plugin/light4j-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mariadb-2.x-plugin/pom.xml | 2 +- .../micronaut-http-client-plugin/pom.xml | 2 +- .../micronaut-http-server-plugin/pom.xml | 2 +- .../apm-sdk-plugin/micronaut-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/motan-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mssql-commons/pom.xml | 2 +- .../apm-sdk-plugin/mssql-jdbc-plugin/pom.xml | 2 +- .../mssql-jtds-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-6.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-common/pom.xml | 2 +- .../nats-2.14.x-2.16.5-plugin/pom.xml | 2 +- .../apm-sdk-plugin/neo4j-4.x-plugin/pom.xml | 2 +- .../netty-socketio-plugin/pom.xml | 2 +- .../nutz-plugins/http-1.x-plugin/pom.xml | 2 +- .../mvc-annotation-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/nutz-plugins/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-common/pom.xml | 2 +- .../apm-sdk-plugin/play-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-sdk-plugin/pom.xml | 2 +- .../postgresql-8.x-plugin/pom.xml | 2 +- .../pulsar-2.2-2.7-plugin/pom.xml | 2 +- .../pulsar-2.8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/pulsar-common/pom.xml | 2 +- .../apm-sdk-plugin/quasar-plugin/pom.xml | 2 +- .../apm-sdk-plugin/rabbitmq-plugin/pom.xml | 2 +- .../redisson-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/resteasy-plugin/pom.xml | 2 +- .../resteasy-server-3.x-plugin/pom.xml | 2 +- .../resteasy-server-4.x-plugin/pom.xml | 2 +- .../resteasy-server-6.x-plugin/pom.xml | 2 +- .../rocketMQ-3.x-plugin/pom.xml | 2 +- .../rocketMQ-4.x-plugin/pom.xml | 2 +- .../rocketMQ-5.x-plugin/pom.xml | 2 +- .../rocketMQ-client-java-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/servicecomb-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../shardingsphere-plugins/pom.xml | 2 +- .../sharding-sphere-3.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.0.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.1.0-plugin/pom.xml | 2 +- .../sharding-sphere-5.0.0-plugin/pom.xml | 2 +- .../apm-sdk-plugin/sofarpc-plugin/pom.xml | 2 +- .../apm-sdk-plugin/solon-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/solrj-7.x-plugin/pom.xml | 2 +- .../async-annotation-plugin/pom.xml | 2 +- .../concurrent-util-4.x-plugin/pom.xml | 2 +- .../spring-plugins/core-patch/pom.xml | 2 +- .../mvc-annotation-3.x-plugin/pom.xml | 2 +- .../mvc-annotation-4.x-plugin/pom.xml | 2 +- .../mvc-annotation-5.x-plugin/pom.xml | 2 +- .../mvc-annotation-commons/pom.xml | 2 +- .../apm-sdk-plugin/spring-plugins/pom.xml | 2 +- .../resttemplate-3.x-plugin/pom.xml | 2 +- .../resttemplate-4.x-plugin/pom.xml | 2 +- .../resttemplate-commons/pom.xml | 2 +- .../scheduled-annotation-plugin/pom.xml | 2 +- .../spring-cloud/netflix-plugins/pom.xml | 2 +- .../spring-cloud-feign-1.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-cloud/pom.xml | 2 +- .../spring-cloud-feign-2.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-commons/pom.xml | 2 +- .../spring-kafka-1.x-plugin/pom.xml | 2 +- .../spring-kafka-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../spymemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/struts2-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/thrift-plugin/pom.xml | 2 +- .../apm-sdk-plugin/tomcat-10x-plugin/pom.xml | 2 +- .../tomcat-7.x-8.x-plugin/pom.xml | 2 +- .../tomcat-thread-pool-plugin/pom.xml | 2 +- .../apm-sdk-plugin/undertow-plugins/pom.xml | 2 +- .../undertow-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/vertx-plugins/pom.xml | 2 +- .../vertx-core-3.x-plugin/pom.xml | 2 +- .../vertx-core-4.x-plugin/pom.xml | 2 +- .../websphere-liberty-23.x-plugin/pom.xml | 2 +- .../xmemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-test-tools/pom.xml | 2 +- .../apm-toolkit-kafka-activation/pom.xml | 2 +- .../apm-toolkit-log4j-1.x-activation/pom.xml | 2 +- .../apm-toolkit-log4j-2.x-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-logging-common/pom.xml | 2 +- .../apm-toolkit-meter-activation/pom.xml | 2 +- .../apm-toolkit-micrometer-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-trace-activation/pom.xml | 2 +- .../apm-toolkit-webflux-activation/pom.xml | 2 +- apm-sniffer/apm-toolkit-activation/pom.xml | 2 +- .../jdk-forkjoinpool-plugin/pom.xml | 2 +- .../bootstrap-plugins/jdk-http-plugin/pom.xml | 2 +- .../jdk-threading-plugin/pom.xml | 2 +- .../jdk-threadpool-plugin/pom.xml | 2 +- apm-sniffer/bootstrap-plugins/pom.xml | 2 +- apm-sniffer/bytebuddy-patch/pom.xml | 2 +- .../impala-jdbc-2.6.x-plugin/pom.xml | 2 +- apm-sniffer/expired-plugins/pom.xml | 2 +- .../caffeine-3.x-plugin/pom.xml | 5 ++- .../customize-enhance-plugin/pom.xml | 2 +- .../ehcache-2.x-plugin/pom.xml | 2 +- .../fastjson-1.2.x-plugin/pom.xml | 2 +- .../gson-2.8.x-plugin/pom.xml | 2 +- .../guava-cache-plugin/pom.xml | 2 +- .../jackson-2.x-plugin/pom.xml | 2 +- .../kotlin-coroutine-plugin/pom.xml | 2 +- .../mybatis-3.x-plugin/pom.xml | 2 +- .../nacos-client-2.x-plugin/pom.xml | 2 +- .../netty-http-4.1.x-plugin/pom.xml | 2 +- .../mvc-annotation-6.x-plugin/pom.xml | 2 +- .../gateway-2.0.x-plugin/pom.xml | 2 +- .../gateway-2.1.x-plugin/pom.xml | 2 +- .../gateway-3.x-plugin/pom.xml | 2 +- .../gateway-4.x-plugin/pom.xml | 2 +- .../optional-spring-cloud/pom.xml | 2 +- .../optional-spring-plugins/pom.xml | 2 +- .../resttemplate-6.x-plugin/pom.xml | 2 +- .../spring-annotation-plugin/pom.xml | 2 +- .../spring-tx-plugin/pom.xml | 2 +- .../spring-webflux-5.x-plugin/pom.xml | 2 +- .../spring-webflux-6.x-plugin/pom.xml | 2 +- apm-sniffer/optional-plugins/pom.xml | 2 +- .../quartz-scheduler-2.x-plugin/pom.xml | 2 +- .../sentinel-1.x-plugin/pom.xml | 2 +- .../shenyu-2.4.x-plugin/pom.xml | 2 +- .../trace-ignore-plugin/pom.xml | 2 +- .../trace-sampler-cpu-policy-plugin/pom.xml | 2 +- .../zookeeper-3.4.x-plugin/pom.xml | 2 +- .../kafka-config-extension/pom.xml | 2 +- .../kafka-reporter-plugin/pom.xml | 2 +- apm-sniffer/optional-reporter-plugins/pom.xml | 2 +- apm-sniffer/pom.xml | 2 +- changes/changes-9.4.0.md | 33 +++++++++++++++++++ pom.xml | 2 +- 237 files changed, 272 insertions(+), 263 deletions(-) create mode 100644 changes/changes-9.4.0.md diff --git a/CHANGES.md b/CHANGES.md index 2a797ed4cc..2e024d8c17 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,35 +2,12 @@ Changes by Version ================== Release Notes. -9.4.0 +9.5.0 ------------------ -* Upgrade nats plugin to support 2.16.5 -* Add agent self-observability. -* Fix intermittent ClassCircularityError by preloading ThreadLocalRandom since ByteBuddy 1.12.11 -* Add witness class/method for resteasy-server plugin(v3/v4/v6) -* Add async-profiler feature for performance analysis -* Support db.instance tag,db.collection tag and AggregateOperation span for mongodb plugin(3.x/4.x) -* Improve CustomizeConfiguration by avoiding repeatedly resolve file config -* Add empty judgment for constructorInterceptPoint -* Bump up gRPC to 1.68.1 -* Bump up netty to 4.1.115.Final -* Fix the `CreateAopProxyInterceptor` in the Spring core-patch to prevent it from changing the implementation of the - Spring AOP proxy -* Support Tracing for GlobalFilter and GatewayFilter in Spring Gateway -* [doc] Enhance Custom Trace Ignoring Plugin document about conflicts with the plugin of **sampler plugin with CPU - policy** -* [doc] Add Spring Gateway Plugin document -* [doc] Add 4 menu items guiding users to find important notices for Spring Annotation Plugin, Custom Trace Ignoring - Plugin, Kotlin Coroutine Plugin, and Spring Gateway Plugin -* Change context and parent entry span propagation mechanism from gRPC ThreadLocal context to SkyWalking native dynamic - field as new propagation mechanism, to better support async scenarios. -* Add Caffeine plugin as optional. -* Add Undertow 2.1.7.final+ worker thread pool metrics. -* Support for tracking in spring gateway versions 4.1.2 and above. -* Fix `ConsumeDriver` running status concurrency issues. -All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) ------------------ Find change logs of all versions [here](changes). diff --git a/apm-application-toolkit/apm-toolkit-kafka/pom.xml b/apm-application-toolkit/apm-toolkit-kafka/pom.xml index d6edf28b6c..7c3716b0e5 100644 --- a/apm-application-toolkit/apm-toolkit-kafka/pom.xml +++ b/apm-application-toolkit/apm-toolkit-kafka/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml index f6f5121d89..cb8993d17c 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml index e60e68ed89..1c3d85a7fe 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml index 1c14cfc123..7c5a107738 100644 --- a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-meter/pom.xml b/apm-application-toolkit/apm-toolkit-meter/pom.xml index a5860a3f51..30d8dcf028 100644 --- a/apm-application-toolkit/apm-toolkit-meter/pom.xml +++ b/apm-application-toolkit/apm-toolkit-meter/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml index 908892f0d7..8a266900ab 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml index e2ee0ea1ca..424c5af99c 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml index 3261da8b71..121ce32141 100644 --- a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml +++ b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-trace/pom.xml b/apm-application-toolkit/apm-toolkit-trace/pom.xml index f1ae80be59..89e24e7416 100644 --- a/apm-application-toolkit/apm-toolkit-trace/pom.xml +++ b/apm-application-toolkit/apm-toolkit-trace/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-webflux/pom.xml b/apm-application-toolkit/apm-toolkit-webflux/pom.xml index b1a13f52e5..8320b65eac 100644 --- a/apm-application-toolkit/apm-toolkit-webflux/pom.xml +++ b/apm-application-toolkit/apm-toolkit-webflux/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/pom.xml b/apm-application-toolkit/pom.xml index 73586f919b..360309be0f 100644 --- a/apm-application-toolkit/pom.xml +++ b/apm-application-toolkit/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 apm-application-toolkit diff --git a/apm-commons/apm-datacarrier/pom.xml b/apm-commons/apm-datacarrier/pom.xml index 781cfec5d6..83c7bd6026 100644 --- a/apm-commons/apm-datacarrier/pom.xml +++ b/apm-commons/apm-datacarrier/pom.xml @@ -21,7 +21,7 @@ java-agent-commons org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/apm-util/pom.xml b/apm-commons/apm-util/pom.xml index 7fa74fac6b..e2ed3c0faf 100644 --- a/apm-commons/apm-util/pom.xml +++ b/apm-commons/apm-util/pom.xml @@ -20,7 +20,7 @@ java-agent-commons org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/pom.xml b/apm-commons/pom.xml index 522ec3086d..54d6c00fbe 100644 --- a/apm-commons/pom.xml +++ b/apm-commons/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/apm-network/pom.xml b/apm-protocol/apm-network/pom.xml index 3edb1f9c05..eda94f4e65 100644 --- a/apm-protocol/apm-network/pom.xml +++ b/apm-protocol/apm-network/pom.xml @@ -21,7 +21,7 @@ java-agent-protocol org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/pom.xml b/apm-protocol/pom.xml index 47ffbfe637..b71653c24a 100644 --- a/apm-protocol/pom.xml +++ b/apm-protocol/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index b22c082035..19241fcd2c 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-agent-core diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 0112c21e1c..6454eed897 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-agent diff --git a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml index 684cc8bf76..55fef10c59 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml index 4fa869a203..3985b5397c 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml index 85734b3665..92d9f01a3b 100644 --- a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml index 8df069e81d..2ac5d6da16 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml index 29653163a7..b7828f4736 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml index 0b19011684..8e697d2f94 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml index a3c50c7f1e..db15e7eede 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml index be8e1e10d9..ec7c1edfcb 100644 --- a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml index 4cbdd59f07..0007f48f52 100644 --- a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml index 977b8d5fa4..e5bc1cc77b 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml index ca29c17a63..1c4f31078e 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml index 9ed08a7919..b82413193c 100644 --- a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml index 6440a943a0..a1345ce94b 100644 --- a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml index 20e3580fc3..3f18e7dd91 100644 --- a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml index 8c749b4cc3..a02c6c825b 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml index bfccb45b00..12f4545553 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml index 618a7bc934..142a1af779 100644 --- a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml index c97d28f835..c5d9f1c622 100644 --- a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml index 290abe63bf..b6d66a13c2 100644 --- a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml index 54f688dc68..250b40747f 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml index f8b7395ae4..e09e68f0e9 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml index 9e7a515ce4..c45ce3088b 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml index 71d8e01916..23a54b3dea 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml index 6c584299cf..14d0c6dd8e 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml index 52efdd6390..7f3f74e7e4 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml index cfb502b8f7..9ca6fa2a0b 100644 --- a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml index a2d47d0c11..4a1104df96 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml index 0e10a3c699..66158a23c6 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml index 162d069a9b..e0498309df 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml index 29ca4de3b1..23d01d02b6 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml index 4ae4ea02d3..fe073bab48 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml index ac3528c7e0..cb61046af8 100644 --- a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml index 2743a90796..ff67ed2756 100644 --- a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml index 288189e69b..4aaeb95e96 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml index d514800ee5..16f50fca6b 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml index f0a274a768..b2007ad0c3 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml index f1f10b73ce..5214288cc1 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml index d13e127585..9ae21f8860 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml index 23d0caea0e..a659f766be 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml index faf700318e..fb58ba4b09 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-grizzly-2.x-4.x-work-threadpool-plugin diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml index 1d9b3fdbf5..b1fc5775ae 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-grpc-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml index c6cba9b84d..e17161bf7e 100644 --- a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml index f4de4fa62b..8c50a7eb03 100755 --- a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml index bc77540d04..77b14b76b1 100644 --- a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-hbase-1.x-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml index f9d9b2d48b..348d7a23bb 100644 --- a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml index ccaeccbe9a..e2786ece2d 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-httpClient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml index 84d552aee1..a59dde7d37 100644 --- a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-httpasyncclient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml index 190ef1b0df..befc85cd6e 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-httpclient-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml index 9375758907..030bace429 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-httpclient-5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml index 30e4f38ff2..32f90e5522 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-httpclient-commons diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml index cb83a4f056..1e469dd79c 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ hutool-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml index b028d224fd..ac5912a1d5 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml index bea536a191..a6a0b0bc03 100644 --- a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml index 4b3767a0dc..d0d31dc340 100644 --- a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml index 0f6be0acff..b665da8275 100755 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml index 49ec8c40cc..540074e372 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking jedis-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml index 35893a8c2d..8527b72e9b 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ jedis-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml index fff2a09c61..fa0049c0a4 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT diff --git a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml index 1d08051a7e..19695c5449 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml index eba3b4768a..fafc35d46a 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml index 2d3577a606..49f4b892af 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml index ea620bb103..911028beea 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml index e4d2cf3890..8765b520cc 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml index 7fae8c33d1..7210f0e51c 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml index ad6d25acdd..85f58596a8 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml index 21d38befca..b0625e34f5 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT jetty-plugins diff --git a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml index e461d1cf3b..f3befb3a02 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml index b44f44d3d0..b3575f408e 100644 --- a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml index bd6687307d..56f7535d9d 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-kafka-commons diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml index 7ec88ebbc3..44cdcc8a48 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml index 6db9466b71..35f9c49d78 100644 --- a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml index 3835354ea5..05b0f3a44f 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-lettuce-5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml index cc692737a5..82ec21b53e 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml @@ -20,7 +20,7 @@ light4j-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml index 89f4778d13..940a6cc9d3 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT light4j-plugins diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml index 4ef60ef291..88aaaa4f20 100644 --- a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml index 0ffd372cfd..df3c7fc819 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml index e48c03c52e..a97560446d 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml index d4b2ff1753..7c2f4c9153 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml index 2d4b0ec700..87d6518afe 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml index c521caf896..6181f336e0 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-mongodb-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml index 504554f186..903fe7e6f1 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-mongodb-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml index ee2b1dc842..74f25bdc82 100644 --- a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml index c612a36766..bfea14ea91 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml index 39812a801a..9129842df7 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml index f55cc9c4e1..05cc1cc520 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml index 4356ae4288..0e567b465c 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml index ba7bd8dc18..dfb7c3927c 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml index 371bbad8f8..4b72ab25d6 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml index 7640bd37ef..ab027cc967 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml index 843fc387d0..61ffd1e302 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml index 7603cb938c..687c26c0c1 100644 --- a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml index 039e28556f..a90718c960 100644 --- a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml index 777579e6d9..b09d263257 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml index 038c1b4871..633775692b 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml index 273c4dd296..cf6619cce9 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT nutz-plugins diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml index fea937cfad..ca6b0f410c 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml index b709dab5d4..4440fb707d 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml index 4127a432cf..c1d3854825 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml index 013ffdf693..f3588227a6 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml index 617ffe7406..1e96e2c0b6 100644 --- a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-play-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index debaf5bf76..cd92e19f81 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking java-agent-sniffer - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-sdk-plugin diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml index 2a7c718929..bfccc6c6dc 100755 --- a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml index 1b57fb9c45..85eea26033 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml index aaefac8f38..7398535cdc 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml index 256a1dc1cc..555be168e9 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml index a42bb810bb..77a4db4d95 100644 --- a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-quasar-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml index 9d0e0b0ffe..c8add46003 100644 --- a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml index c8a11445d4..8f1c0c959a 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-redisson-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml index 25bd66f0a7..e00a66d323 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT resteasy-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml index 69d1761dd1..845ba79186 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT resteasy-server-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml index a15a08e6e4..d4a2f6fac5 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT resteasy-server-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml index 0e13f993b9..653cac9f96 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT resteasy-server-6.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml index 933fd8465a..24b5e08ca1 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml index 2c3c4cb46b..091d0d2c8e 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml index bcda3ff1b0..e25561ad98 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml index 208087afb8..2e0cb1a88c 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml index fe95b1df3a..d416b50a87 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml index 5a9023f5a0..a423494f0b 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ servicecomb-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml index 03d6992c14..a5d3febb25 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml index 120ef8335a..d630c327fe 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml index e3fc5f69dc..969e0d71f9 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml index 5b83c087ce..6378eb83b5 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml index 2a147a76b3..057f200f8a 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml index 0bcfc585a3..abd34c6675 100644 --- a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml index 34efbc6d2e..305501d2d6 100644 --- a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT solon-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml index 8ab65b23b9..e39497748f 100644 --- a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml index b056c8adb3..dd621bb928 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml index f76e078491..c80e8a2e37 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml index c46812fcd1..e99e3c78e7 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml index e06e754cd2..9c5e1083d4 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml index b63777a63e..8081633e00 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml index 41d9d85f1f..90da81f340 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml @@ -19,7 +19,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml index a4aa39a70a..d439f9f138 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml index daf2214ab2..9f03ceb189 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT spring-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml index cda376e6d9..8090108737 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml index 72fe157d21..0f93f494f3 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml index bdfb781386..7d595c3990 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml index 0953926c68..b2a8839a14 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml index f66650161e..fcbef61d3d 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT netflix-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml index 7ab120108c..51d577a2b2 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking netflix-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-spring-cloud-feign-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml index bb5ebcf67b..50bb2fc000 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT spring-cloud diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml index 8f8da9a5ec..268c60f4d3 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-spring-cloud-feign-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml index b0eca05cc1..10764dce33 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml index 0b9af9a642..4f88e7dd08 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-spring-kafka-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml index 4714fb7076..8268920161 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-spring-kafka-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml index 413b41440c..302a39ffa5 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml index 49428bd872..3c613e71fc 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml index 9630275ea3..48a234f1c5 100644 --- a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-spymemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml index fa90818a41..6b4ed9b5a9 100644 --- a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml index e3c9c5a399..ff6eb323ba 100644 --- a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml index b36a087743..59e4fa7ccf 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml index cfcd3d7b94..5a38651fca 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml index 356f3ae1f2..81751b7e30 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml index e02b868b8d..de51de6721 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT undertow-plugins diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml index 4a6b293848..68bfbbf7ea 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ undertow-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml index d1c1359a35..12c14420d4 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml index fa08a46702..8ee54e78b7 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT vertx-plugins diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml index d4b8889bd5..7677806266 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml index d2bed74c43..f47dcf2da0 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml index 887fbb702e..b0ef592eb7 100644 --- a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml index 6cac80505e..4e4df94336 100644 --- a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-xmemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml index 66704f142c..88e8223ae4 100644 --- a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-test-tools/pom.xml b/apm-sniffer/apm-test-tools/pom.xml index 26e56d7774..c9a74371ee 100644 --- a/apm-sniffer/apm-test-tools/pom.xml +++ b/apm-sniffer/apm-test-tools/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-test-tools diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml index 8a2d66f56f..eb9bd221e1 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml index a8b14ecd3b..2a71222db5 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml index 36d099f5fd..00938c5768 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml index a77fad6f98..3fc275601b 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml index 05d9223fe1..22079cb1a7 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml index 519a5c3360..44838ec361 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml index e8980c845c..a3510d1c36 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml index a9695ba387..0b654a04ed 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml index 091c15950f..85caf42f41 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml index 5826a56466..ea1208fcaa 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/pom.xml index 29e360a6c0..13a2b11abc 100644 --- a/apm-sniffer/apm-toolkit-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml index 94b80ea606..8519bb6f76 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml index 6e3f0886b4..c121b39605 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml index 7754fc0800..be2ea6621a 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml index 035168e0d6..3f3f7fda66 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml @@ -20,7 +20,7 @@ bootstrap-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/pom.xml b/apm-sniffer/bootstrap-plugins/pom.xml index 30625b1b5f..0af18c26df 100644 --- a/apm-sniffer/bootstrap-plugins/pom.xml +++ b/apm-sniffer/bootstrap-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bytebuddy-patch/pom.xml b/apm-sniffer/bytebuddy-patch/pom.xml index 3c351af416..9891184099 100644 --- a/apm-sniffer/bytebuddy-patch/pom.xml +++ b/apm-sniffer/bytebuddy-patch/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking java-agent-sniffer - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml index 8488cf4e05..1e73ce957f 100644 --- a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml +++ b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml @@ -24,7 +24,7 @@ org.apache.skywalking expired-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-impala-jdbc-2.6.x-plugin diff --git a/apm-sniffer/expired-plugins/pom.xml b/apm-sniffer/expired-plugins/pom.xml index 205ed460f1..f05ba0911c 100644 --- a/apm-sniffer/expired-plugins/pom.xml +++ b/apm-sniffer/expired-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml index 3170ed81a2..3b1a717fb1 100644 --- a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml @@ -17,13 +17,12 @@ ~ --> - + 4.0.0 org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-caffeine-3.x-plugin diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml index ac5116d0bd..56e06888fd 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml index d5c5381557..ee76290141 100644 --- a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml index 42bffedf1d..5308320d5d 100644 --- a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-fastjson-1.x-plugin diff --git a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml index c45e4d70be..a328a8d4df 100644 --- a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-gson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml index f021f273dc..45653d891a 100644 --- a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-guava-cache-plugin diff --git a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml index 3cd08b5c9f..35228a0af8 100644 --- a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-jackson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml index bf9ed9c729..b029145a05 100644 --- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-kotlin-coroutine-plugin diff --git a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml index 67db73c337..c66c1e6919 100644 --- a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-mybatis-3.x-plugin diff --git a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml index 9d185c1b44..2c8279b547 100644 --- a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml index 0776e16111..ca4e3737f7 100644 --- a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml index 59826b659c..b6972d435d 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml @@ -19,7 +19,7 @@ optional-spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml index 3e1ccd7e94..6ca7443606 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-spring-cloud-gateway-2.0.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml index 555c650198..7fd5f57275 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-spring-cloud-gateway-2.1.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml index 139917052e..e50550cd3a 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml index 59f5bb76fb..ffa82d61b4 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml index 3554a8c1e0..a884700ba6 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT optional-spring-cloud diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml index a5f1256ee7..71e1f715f2 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml index 58284c10b3..772211aa4d 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ optional-spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml index 87669f820f..d43d45a461 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml index 14299642e3..77ef74f7bb 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml index 1338ef5105..7674b94aee 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml index 7350b5b8aa..0272715a1a 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml index 05f41f83f9..d5c31745e7 100644 --- a/apm-sniffer/optional-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml index ead3f06035..f7c6a7559c 100644 --- a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-quartz-scheduler-2.x-plugin diff --git a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml index 3d63d85ece..cffef0e57e 100644 --- a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml index d4201cbbce..b76db5ddcd 100644 --- a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml index ed86661634..2c4c16d8e8 100644 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml index e7a6318374..7b3b9198eb 100644 --- a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml index 93de4d4018..4b85b133fc 100644 --- a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT apm-zookeeper-3.4.x-plugin diff --git a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml index c583447e44..b17f873159 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml @@ -20,7 +20,7 @@ optional-reporter-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml index 0f795f03a0..a9ba55cc5a 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml @@ -21,7 +21,7 @@ optional-reporter-plugins org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/pom.xml b/apm-sniffer/optional-reporter-plugins/pom.xml index 4cf950ba70..0180b036d0 100644 --- a/apm-sniffer/optional-reporter-plugins/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/pom.xml b/apm-sniffer/pom.xml index 98cfaf4012..3908e24a0d 100644 --- a/apm-sniffer/pom.xml +++ b/apm-sniffer/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT 4.0.0 diff --git a/changes/changes-9.4.0.md b/changes/changes-9.4.0.md new file mode 100644 index 0000000000..c3fa1a4b7e --- /dev/null +++ b/changes/changes-9.4.0.md @@ -0,0 +1,33 @@ +Changes by Version +================== +Release Notes. + +9.4.0 +------------------ + +* Upgrade nats plugin to support 2.16.5 +* Add agent self-observability. +* Fix intermittent ClassCircularityError by preloading ThreadLocalRandom since ByteBuddy 1.12.11 +* Add witness class/method for resteasy-server plugin(v3/v4/v6) +* Add async-profiler feature for performance analysis. This requires OAP server 10.2.0 +* Support db.instance tag,db.collection tag and AggregateOperation span for mongodb plugin(3.x/4.x) +* Improve CustomizeConfiguration by avoiding repeatedly resolve file config +* Add empty judgment for constructorInterceptPoint +* Bump up gRPC to 1.68.1 +* Bump up netty to 4.1.115.Final +* Fix the `CreateAopProxyInterceptor` in the Spring core-patch to prevent it from changing the implementation of the + Spring AOP proxy +* Support Tracing for GlobalFilter and GatewayFilter in Spring Gateway +* [doc] Enhance Custom Trace Ignoring Plugin document about conflicts with the plugin of **sampler plugin with CPU + policy** +* [doc] Add Spring Gateway Plugin document +* [doc] Add 4 menu items guiding users to find important notices for Spring Annotation Plugin, Custom Trace Ignoring + Plugin, Kotlin Coroutine Plugin, and Spring Gateway Plugin +* Change context and parent entry span propagation mechanism from gRPC ThreadLocal context to SkyWalking native dynamic + field as new propagation mechanism, to better support async scenarios. +* Add Caffeine plugin as optional. +* Add Undertow 2.1.7.final+ worker thread pool metrics. +* Support for tracking in spring gateway versions 4.1.2 and above. +* Fix `ConsumeDriver` running status concurrency issues. + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/222?closed=1) \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7071bb6d5c..1e546b07f4 100755 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent - 9.4.0-SNAPSHOT + 9.5.0-SNAPSHOT org.apache From 35856b4bca9aa5b077e3c7f67b44a7c02f3f9516 Mon Sep 17 00:00:00 2001 From: peachisai <2581009893@qq.com> Date: Sun, 9 Mar 2025 09:39:41 +0800 Subject: [PATCH 057/114] Add the virtual thread executor plugin (#751) --- .github/workflows/plugins-jdk21-test.0.yaml | 1 + CHANGES.md | 1 + .../trace/component/ComponentsDefine.java | 2 + .../apm/agent/core/context/tag/Tags.java | 5 + .../pom.xml | 46 ++++++++ ...adPerTaskExecutorConstructInterceptor.java | 33 ++++++ .../ThreadPerTaskExecutorRunInterceptor.java | 81 ++++++++++++++ ...dPerTaskExecutorFutureInstrumentation.java | 90 +++++++++++++++ ...TaskExecutorTaskRunnerInstrumentation.java | 90 +++++++++++++++ .../src/main/resources/skywalking-plugin.def | 18 +++ apm-sniffer/bootstrap-plugins/pom.xml | 1 + .../Application-toolkit-log4j-1.x.md | 2 +- .../java-agent/Bootstrap-plugins.md | 1 + .../service-agent/java-agent/Plugin-list.md | 1 + .../bin/startup.sh | 21 ++++ .../config/expectedData.yaml | 101 +++++++++++++++++ .../configuration.yml | 22 ++++ .../pom.xml | 103 ++++++++++++++++++ .../src/main/assembly/assembly.xml | 41 +++++++ .../jdk/virtualThread/Application.java | 73 +++++++++++++ .../src/main/resources/application.yaml | 21 ++++ .../support-version.list | 17 +++ 22 files changed, 770 insertions(+), 1 deletion(-) create mode 100644 apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml create mode 100644 apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorConstructInterceptor.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorRunInterceptor.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorFutureInstrumentation.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorTaskRunnerInstrumentation.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/resources/skywalking-plugin.def create mode 100644 test/plugin/scenarios/jdk-virtual-thread-executor-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/jdk-virtual-thread-executor-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/jdk-virtual-thread-executor-scenario/configuration.yml create mode 100644 test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml create mode 100644 test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/virtualThread/Application.java create mode 100644 test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/jdk-virtual-thread-executor-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk21-test.0.yaml b/.github/workflows/plugins-jdk21-test.0.yaml index 2851619f12..87b058284c 100644 --- a/.github/workflows/plugins-jdk21-test.0.yaml +++ b/.github/workflows/plugins-jdk21-test.0.yaml @@ -56,6 +56,7 @@ jobs: matrix: case: - spring-6.x-scenario + - jdk-virtual-thread-executor-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 2e024d8c17..74ab4201d7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ Release Notes. 9.5.0 ------------------ +* Add the virtual thread executor plugin All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index e10b207ce5..d81ba8c136 100755 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -260,4 +260,6 @@ public class ComponentsDefine { public static final OfficialComponent SOLON_MVC = new OfficialComponent(158, "SolonMVC"); public static final OfficialComponent CAFFEINE = new OfficialComponent(160, "Caffeine"); + + public static final OfficialComponent THREAD_PER_TASK_EXECUTOR = new OfficialComponent(161, "ThreadPerTask-executor"); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java index e538241368..18093a453e 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java @@ -155,6 +155,11 @@ public static final class HTTP { */ public static final StringTag THREAD_ID = new StringTag(23, "thread.id"); + /** + * THREAD_CARRIER represents the actual operating system thread that carries out the execution of the virtual thread. + */ + public static final StringTag THREAD_CARRIER = new StringTag(24, "thread.carrier"); + /** * Creates a {@code StringTag} with the given key and cache it, if it's created before, simply return it without * creating a new one. diff --git a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml new file mode 100644 index 0000000000..705560aad1 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml @@ -0,0 +1,46 @@ + + + + + bootstrap-plugins + org.apache.skywalking + 9.5.0-SNAPSHOT + + 4.0.0 + + apm-jdk-virtual-thread-executor-plugin + jar + + apm-jdk-virtual-thread-executor-plugin + http://maven.apache.org + + + UTF-8 + + + + + + + maven-deploy-plugin + + + + + \ No newline at end of file diff --git a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorConstructInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorConstructInterceptor.java new file mode 100644 index 0000000000..c8f18193f9 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorConstructInterceptor.java @@ -0,0 +1,33 @@ +/* + * 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.InstanceConstructorInterceptor; + +public class ThreadPerTaskExecutorConstructInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + if (ContextManager.isActive()) { + objInst.setSkyWalkingDynamicField(ContextManager.capture()); + } + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorRunInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorRunInterceptor.java new file mode 100644 index 0000000000..9cd9289116 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/ThreadPerTaskExecutorRunInterceptor.java @@ -0,0 +1,81 @@ +/* + * 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.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +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 ThreadPerTaskExecutorRunInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + Object skyWalkingDynamicField = objInst.getSkyWalkingDynamicField(); + if (skyWalkingDynamicField == null) { + return; + } + + if (!(skyWalkingDynamicField instanceof ContextSnapshot)) { + return; + } + + AbstractSpan span = ContextManager.createLocalSpan(getOperationName(objInst, method)); + span.setComponent(ComponentsDefine.THREAD_PER_TASK_EXECUTOR); + setCarrierThread(span); + + ContextSnapshot contextSnapshot = (ContextSnapshot) skyWalkingDynamicField; + ContextManager.continued(contextSnapshot); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().log(t); + } + } + + private String getOperationName(EnhancedInstance objInst, Method method) { + return objInst.getClass().getName() + "." + method.getName(); + } + + private void setCarrierThread(AbstractSpan span) { + String threadInfo = Thread.currentThread().toString(); + if (threadInfo.startsWith("VirtualThread")) { + String[] parts = threadInfo.split("@"); + if (parts.length >= 1) { + Tags.THREAD_CARRIER.set(span, parts[1]); + } + } + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorFutureInstrumentation.java b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorFutureInstrumentation.java new file mode 100644 index 0000000000..3ed5788a1e --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorFutureInstrumentation.java @@ -0,0 +1,90 @@ +/* + * 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.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class ThreadPerTaskExecutorFutureInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "java.util.concurrent.ThreadPerTaskExecutor$ThreadBoundFuture"; + + private static final String INTERCEPT_RUN_METHOD = "run"; + + private static final String INTERCEPT_RUN_HANDLE = "org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorRunInterceptor"; + + private static final String TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorConstructInterceptor"; + + @Override + public boolean isBootstrapInstrumentation() { + return true; + } + + @Override + protected ClassMatch enhanceClass() { + return MultiClassNameMatch.byMultiClassMatch(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named(INTERCEPT_RUN_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_RUN_HANDLE; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorTaskRunnerInstrumentation.java b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorTaskRunnerInstrumentation.java new file mode 100644 index 0000000000..9a0efd075f --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/ThreadPerTaskExecutorTaskRunnerInstrumentation.java @@ -0,0 +1,90 @@ +/* + * 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.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; + +public class ThreadPerTaskExecutorTaskRunnerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "java.util.concurrent.ThreadPerTaskExecutor$TaskRunner"; + + private static final String INTERCEPT_RUN_METHOD = "run"; + + private static final String INTERCEPT_RUN_HANDLE = "org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorRunInterceptor"; + + private static final String TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorConstructInterceptor"; + + @Override + public boolean isBootstrapInstrumentation() { + return true; + } + + @Override + protected ClassMatch enhanceClass() { + return MultiClassNameMatch.byMultiClassMatch(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named(INTERCEPT_RUN_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_RUN_HANDLE; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..3ab6a970a9 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,18 @@ +# 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-virtual-thread-executor-plugin=org.apache.skywalking.apm.plugin.define.ThreadPerTaskExecutorTaskRunnerInstrumentation +jdk-virtual-thread-executor-plugin=org.apache.skywalking.apm.plugin.define.ThreadPerTaskExecutorFutureInstrumentation \ No newline at end of file diff --git a/apm-sniffer/bootstrap-plugins/pom.xml b/apm-sniffer/bootstrap-plugins/pom.xml index 0af18c26df..22de027237 100644 --- a/apm-sniffer/bootstrap-plugins/pom.xml +++ b/apm-sniffer/bootstrap-plugins/pom.xml @@ -43,6 +43,7 @@ jdk-threading-plugin jdk-threadpool-plugin jdk-forkjoinpool-plugin + jdk-virtual-thread-executor-plugin diff --git a/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md b/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md index b180d164ae..2768fa4a72 100644 --- a/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md +++ b/docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md @@ -14,7 +14,7 @@ log4j.appender.CONSOLE.layout=org.apache.skywalking.apm.toolkit.log.log4j.v1.x.TraceIdPatternLayout ``` -* set `%T` in `layout.ConversionPattern` ( In 2.0-2016, you should use %x, [Why change?](https://github.com/wu-sheng/sky-walking/issues/77) ) +* set `%T` in `layout.ConversionPattern` ( In 2.0-2016, you should use %x, [Why change?](https://github.com/apache/skywalking/issues/77) ) ```properties log4j.appender.CONSOLE.layout.ConversionPattern=%d [%T] %-5p %c{1}:%L - %m%n ``` 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 10dd955a9c..7eec71899a 100644 --- a/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md +++ b/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md @@ -7,6 +7,7 @@ Now, we have the following known bootstrap plugins. * Plugin of JDK Callable and Runnable. Agent is compatible with JDK 1.8+ * Plugin of JDK ThreadPoolExecutor. Agent is compatible with JDK 1.8+ * Plugin of JDK ForkJoinPool. Agent is compatible with JDK 1.8+ +* Plugin of JDK VirtualThreadExecutor. Agent is compatible with JDK 21+ ### HttpURLConnection Plugin Notice The plugin of JDK HttpURLConnection depended on `sun.net.*`. When using Java 9+, You should add some JVM options as follows: 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 847a81dbec..aa85d4bcb2 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -48,6 +48,7 @@ - jackson-2.x - jdk-http-plugin - jdk-threading-plugin +- jdk-virtual-thread-executor-plugin - jedis-2.x-3.x - jedis-4.x - jetty-client-9.0 diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/bin/startup.sh b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/bin/startup.sh new file mode 100644 index 0000000000..ac52eb1f0c --- /dev/null +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-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-virtual-thread-executor-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/config/expectedData.yaml b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..f2ccbf3ed1 --- /dev/null +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/config/expectedData.yaml @@ -0,0 +1,101 @@ +# 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-virtual-thread-executor-scenario + segmentSize: ge 0 + segments: + - segmentId: not null + spans: + - operationName: GET:/case + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/virtual-thread-executor-scenario/case'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + - segmentId: not null + spans: + - operationName: /apache/skywalking + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: github.com:443 + skipAnalysis: false + tags: + - {key: url, value: 'https://github.com/apache/skywalking'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + - operationName: java.util.concurrent.ThreadPerTaskExecutor$TaskRunner.run + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 161 + isError: false + spanType: Local + skipAnalysis: false + tags: + - { key: thread.carrier, value: not null } + refs: + - { parentEndpoint: 'GET:/case', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: jdk-virtual-thread-executor-scenario, traceId: not null } + + - segmentId: not null + spans: + - operationName: /apache/skywalking + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: github.com:443 + skipAnalysis: false + tags: + - { key: url, value: 'https://github.com/apache/skywalking' } + - { key: http.method, value: GET } + - { key: http.status_code, value: '200' } + - operationName: java.util.concurrent.ThreadPerTaskExecutor$ThreadBoundFuture.run + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 161 + isError: false + spanType: Local + skipAnalysis: false + tags: + - { key: thread.carrier, value: not null } + refs: + - { parentEndpoint: 'GET:/case', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: jdk-virtual-thread-executor-scenario, traceId: not null } diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/configuration.yml b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/configuration.yml new file mode 100644 index 0000000000..f36c72f82e --- /dev/null +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-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/virtual-thread-executor-scenario/case +healthCheck: http://localhost:8080/virtual-thread-executor-scenario/healthCheck +runningMode: with_bootstrap +withPlugins: apm-jdk-virtual-thread-executor-plugin-*.jar +startScript: ./bin/startup.sh diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml new file mode 100644 index 0000000000..686330b61a --- /dev/null +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml @@ -0,0 +1,103 @@ + + + + 4.0.0 + + org.apache.skywalking + jdk-virtual-thread-executor-scenario + 5.0.0 + + + UTF-8 + 21 + 3.8.1 + 2.7.15 + + + skywalking-jdk-virtual-thread-executor-scenario + + + + org.springframework.boot + spring-boot-starter-web + 2.7.15 + + + + org.redisson + redisson + 3.33.0 + + + + + jdk-virtual-thread-executor-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 21 + 21 + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..55f39086fb --- /dev/null +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ./target/jdk-virtual-thread-executor-scenario.jar + ./libs + 0775 + + + \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/virtualThread/Application.java b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/virtualThread/Application.java new file mode 100644 index 0000000000..57aef5d5b6 --- /dev/null +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/virtualThread/Application.java @@ -0,0 +1,73 @@ +/* + * 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.virtualThread; + +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.RestController; +import org.springframework.web.client.RestTemplate; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@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; + + public TestController(final RestTemplate restTemplate) { + this.restTemplate = restTemplate; + this.executorService = Executors.newVirtualThreadPerTaskExecutor(); + } + + @GetMapping("/healthCheck") + public String healthCheck() { + return "Success"; + } + + @GetMapping("/case") + public String testCase() throws ExecutionException, InterruptedException { + Runnable runnable = () -> restTemplate.getForEntity("https://github.com/apache/skywalking", String.class); + executorService.execute(runnable); + + Callable callable = () -> { + restTemplate.getForEntity("https://github.com/apache/skywalking", String.class); + return "success"; + }; + executorService.submit(callable).get(); + + return "success"; + } + } +} diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..0ddde72c7c --- /dev/null +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/src/main/resources/application.yaml @@ -0,0 +1,21 @@ +# 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 + servlet: + context-path: /virtual-thread-executor-scenario + diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/support-version.list b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/support-version.list new file mode 100644 index 0000000000..feef03cdea --- /dev/null +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-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 f67fe0f7fd061fe9f95eb0f52bcf8d4688b557f1 Mon Sep 17 00:00:00 2001 From: peachisai <2581009893@qq.com> Date: Sun, 9 Mar 2025 14:45:32 +0800 Subject: [PATCH 058/114] Add the javadoc plugin for virtual thread executor plugin (#752) --- .../pom.xml | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml index 686330b61a..a9b9bb25f6 100644 --- a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml @@ -98,6 +98,39 @@ 21 + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + false + + + + + org.apache.maven.plugins + maven-jar-plugin + + + empty-javadoc-jar + package + + jar + + + javadoc + ${basedir}/javadoc + + + + \ No newline at end of file From 49d19464a700b83906082982e20e9298dbc4f98b Mon Sep 17 00:00:00 2001 From: GuoHaoZai <44019619+GuoHaoZai@users.noreply.github.com> Date: Tue, 29 Apr 2025 19:12:22 +0800 Subject: [PATCH 059/114] Fix Conflicts apm-jdk-threadpool-plugin conflicts with apm-jdk-forkjoinpool-plugin (#753) --- CHANGES.md | 2 +- .../apm/plugin/AbstractThreadingPoolInterceptor.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 74ab4201d7..1f4fb1347f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,7 +6,7 @@ Release Notes. ------------------ * Add the virtual thread executor plugin - +* Fix Conflicts apm-jdk-threadpool-plugin conflicts with apm-jdk-forkjoinpool-plugin All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) 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 e11c260f42..152064960b 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 @@ -24,6 +24,7 @@ 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.concurrent.ForkJoinTask; public abstract class AbstractThreadingPoolInterceptor implements InstanceMethodsAroundInterceptor { @Override @@ -71,6 +72,8 @@ private boolean notToEnhance(Object[] allArguments) { Object argument = allArguments[0]; // Avoid duplicate enhancement, such as the case where it has already been enhanced by RunnableWrapper or CallableWrapper with toolkit. - return argument instanceof EnhancedInstance && ((EnhancedInstance) argument).getSkyWalkingDynamicField() instanceof ContextSnapshot; + return argument instanceof EnhancedInstance + && ((EnhancedInstance) argument).getSkyWalkingDynamicField() instanceof ContextSnapshot + && !(argument instanceof ForkJoinTask); } } From f971bcf0fd666fae73821e94f00fd20840d91113 Mon Sep 17 00:00:00 2001 From: Evgeniy Devyatykh Date: Wed, 7 May 2025 18:14:51 +0500 Subject: [PATCH 060/114] To prevent NPE use pool name for metrics if JDBC URL is not set. (#754) HikariCP pool can be configured using JDBC URL: ``` HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/simpsons"); ``` or using data source properties ``` Properties props = new Properties(); props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource"); props.setProperty("dataSource.serverName", "localhost"); ... HikariConfig config = new HikariConfig(props); HikariDataSource ds = new HikariDataSource(config) ``` --- CHANGES.md | 1 + .../apm/plugin/hikaricp/PoolingSealInterceptor.java | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1f4fb1347f..aa57174d65 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ Release Notes. * Add the virtual thread executor plugin * Fix Conflicts apm-jdk-threadpool-plugin conflicts with apm-jdk-forkjoinpool-plugin +* Fix NPE in hikaricp-plugin if JDBC URL is not set All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hikaricp/PoolingSealInterceptor.java b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hikaricp/PoolingSealInterceptor.java index 7be4b562c2..a2673afbf9 100644 --- a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hikaricp/PoolingSealInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/hikaricp/PoolingSealInterceptor.java @@ -49,8 +49,13 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { HikariDataSource hikariDataSource = (HikariDataSource) objInst; - ConnectionInfo connectionInfo = URLParser.parser(hikariDataSource.getJdbcUrl()); - String tagValue = connectionInfo.getDatabaseName() + "_" + connectionInfo.getDatabasePeer(); + String tagValue; + if (hikariDataSource.getJdbcUrl() != null) { + ConnectionInfo connectionInfo = URLParser.parser(hikariDataSource.getJdbcUrl()); + tagValue = connectionInfo.getDatabaseName() + "_" + connectionInfo.getDatabasePeer(); + } else { + tagValue = hikariDataSource.getPoolName(); + } final Map>> poolMetricMap = getPoolMetrics(); final Map>> metricConfigMap = getConfigMetrics(); poolMetricMap.forEach((key, value) -> MeterFactory.gauge(METER_NAME, value.apply(hikariDataSource.getHikariPoolMXBean())) From 9e80a4c85ba895083e892f2024611a27846c3c5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Tue, 13 May 2025 14:33:52 +0800 Subject: [PATCH 061/114] Fix MeterService NPE as not initialized in so11y plugin. (#755) --- CHANGES.md | 3 ++ .../apm/agent/core/boot/ServiceManager.java | 4 +++ .../apm/agent/core/so11y/AgentSo11y.java | 31 +++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index aa57174d65..8affde9592 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,9 @@ Release Notes. * Add the virtual thread executor plugin * Fix Conflicts apm-jdk-threadpool-plugin conflicts with apm-jdk-forkjoinpool-plugin * Fix NPE in hikaricp-plugin if JDBC URL is not set +* Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent transfer + initialization. Delay so11y metrics#build when the services are not ready to avoid MeterService status is not + initialized. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java index ab3042646d..015596ad26 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import java.util.ServiceLoader; +import lombok.Getter; 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.agent.core.plugin.loader.AgentClassLoader; @@ -37,6 +38,8 @@ public enum ServiceManager { private static final ILog LOGGER = LogManager.getLogger(ServiceManager.class); private Map bootedServices = Collections.emptyMap(); + @Getter + private volatile boolean isBooted = false; public void boot() { bootedServices = loadAllServices(); @@ -127,6 +130,7 @@ private void onComplete() { LOGGER.error(e, "Service [{}] AfterBoot process fails.", service.getClass().getName()); } } + isBooted = true; } /** diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java index b1468f293a..c8da7ee262 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/so11y/AgentSo11y.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; import org.apache.skywalking.apm.agent.core.meter.Counter; import org.apache.skywalking.apm.agent.core.meter.Histogram; import org.apache.skywalking.apm.agent.core.meter.MeterFactory; @@ -58,6 +59,12 @@ public class AgentSo11y { private static Histogram INTERCEPTOR_TIME_COST; public static void measureTracingContextCreation(boolean forceSampling, boolean ignoredTracingContext) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } if (forceSampling) { if (ignoredTracingContext) { if (PROPAGATED_IGNORE_CONTEXT_COUNTER == null) { @@ -98,6 +105,12 @@ public static void measureTracingContextCreation(boolean forceSampling, boolean } public static void measureTracingContextCompletion(boolean ignoredTracingContext) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } if (ignoredTracingContext) { if (FINISH_IGNORE_CONTEXT_COUNTER == null) { FINISH_IGNORE_CONTEXT_COUNTER = MeterFactory.counter("finished_ignored_context_counter").build(); @@ -112,6 +125,12 @@ public static void measureTracingContextCompletion(boolean ignoredTracingContext } public static void measureLeakedTracingContext(boolean ignoredTracingContext) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } if (ignoredTracingContext) { if (LEAKED_IGNORE_CONTEXT_COUNTER == null) { LEAKED_IGNORE_CONTEXT_COUNTER = MeterFactory @@ -132,6 +151,12 @@ public static void measureLeakedTracingContext(boolean ignoredTracingContext) { } public static void durationOfInterceptor(double timeCostInNanos) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } if (INTERCEPTOR_TIME_COST == null) { INTERCEPTOR_TIME_COST = MeterFactory .histogram("tracing_context_performance") @@ -142,6 +167,12 @@ public static void durationOfInterceptor(double timeCostInNanos) { } public static void errorOfPlugin(String pluginName, String interType) { + if (!ServiceManager.INSTANCE.isBooted()) { + // Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent + // transfer initialization. + // Skip when the services are not ready to avoid MeterService status is not initialized. + return; + } Counter counter = ERROR_COUNTER_CACHE.computeIfAbsent(pluginName + interType, key -> MeterFactory .counter("interceptor_error_counter") .tag("plugin_name", pluginName) From 529d6d7eb31db1306081d078a0689e84201cb3c4 Mon Sep 17 00:00:00 2001 From: tjuwangning <78459090+tjuwangning@users.noreply.github.com> Date: Wed, 28 May 2025 11:26:05 +0800 Subject: [PATCH 062/114] fix parent class enhance issue (#757) --- CHANGES.md | 1 + .../AbstractClassEnhancePluginDefine.java | 8 +++ .../enhance/ClassEnhancePluginDefine.java | 4 ++ .../v2/ClassEnhancePluginDefineV2.java | 4 ++ .../apm/agent/bytebuddy/biz/ChildBar.java | 27 ++++++++ .../apm/agent/bytebuddy/biz/ParentBar.java | 26 ++++++++ .../cases/AbstractInterceptTest.java | 27 +++++++- .../bytebuddy/cases/ReTransform4Test.java | 62 +++++++++++++++++++ 8 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/biz/ChildBar.java create mode 100644 apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/biz/ParentBar.java create mode 100644 apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/cases/ReTransform4Test.java diff --git a/CHANGES.md b/CHANGES.md index 8affde9592..8e58c3459d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Release Notes. * Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent transfer initialization. Delay so11y metrics#build when the services are not ready to avoid MeterService status is not initialized. +* Fix retransform failure when enhancing both parent and child classes. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java index c53e54f0fa..f0ab14a75b 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/AbstractClassEnhancePluginDefine.java @@ -51,6 +51,14 @@ public abstract class AbstractClassEnhancePluginDefine { * New field name. */ public static final String CONTEXT_ATTR_NAME = "_$EnhancedClassField_ws"; + /** + * Getter method name. + */ + public static final String CONTEXT_GETTER_NAME = "getSkyWalkingDynamicField"; + /** + * Setter method name. + */ + public static final String CONTEXT_SETTER_NAME = "setSkyWalkingDynamicField"; /** * Main entrance of enhancing the class. diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java index b595d89e92..ec6628fe95 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.java @@ -19,6 +19,7 @@ package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance; import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.FieldAccessor; @@ -102,6 +103,9 @@ protected DynamicType.Builder enhanceInstance(TypeDescription typeDescription newClassBuilder = newClassBuilder.defineField( CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE) .implement(EnhancedInstance.class) + .defineMethod(CONTEXT_GETTER_NAME, Object.class, Visibility.PUBLIC) + .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME)) + .defineMethod(CONTEXT_SETTER_NAME, void.class, Visibility.PUBLIC).withParameters(Object.class) .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME)); context.extendObjectCompleted(); } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/ClassEnhancePluginDefineV2.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/ClassEnhancePluginDefineV2.java index 8ea6cdfb99..3423ac1392 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/ClassEnhancePluginDefineV2.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/v2/ClassEnhancePluginDefineV2.java @@ -18,6 +18,7 @@ package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2; import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.FieldAccessor; @@ -135,6 +136,9 @@ protected DynamicType.Builder enhanceInstance(TypeDescription typeDescription newClassBuilder = newClassBuilder.defineField( CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE) .implement(EnhancedInstance.class) + .defineMethod(CONTEXT_GETTER_NAME, Object.class, Visibility.PUBLIC) + .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME)) + .defineMethod(CONTEXT_SETTER_NAME, void.class, Visibility.PUBLIC).withParameters(Object.class) .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME)); context.extendObjectCompleted(); } diff --git a/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/biz/ChildBar.java b/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/biz/ChildBar.java new file mode 100644 index 0000000000..e7ac8d49ff --- /dev/null +++ b/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/biz/ChildBar.java @@ -0,0 +1,27 @@ +/* + * 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.agent.bytebuddy.biz; + +public class ChildBar extends ParentBar { + + public String sayHelloChild() { + return "Joe"; + } + +} diff --git a/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/biz/ParentBar.java b/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/biz/ParentBar.java new file mode 100644 index 0000000000..6113b4c41a --- /dev/null +++ b/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/biz/ParentBar.java @@ -0,0 +1,26 @@ +/* + * 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.agent.bytebuddy.biz; + +public class ParentBar { + + public String sayHelloParent() { + return "Joe"; + } +} diff --git a/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/cases/AbstractInterceptTest.java b/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/cases/AbstractInterceptTest.java index ba9cf4d372..627fc8888d 100644 --- a/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/cases/AbstractInterceptTest.java +++ b/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/cases/AbstractInterceptTest.java @@ -24,6 +24,7 @@ import net.bytebuddy.agent.builder.SWAgentBuilderDefault; import net.bytebuddy.agent.builder.SWDescriptionStrategy; import net.bytebuddy.agent.builder.SWNativeMethodStrategy; +import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.implementation.FieldAccessor; import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.implementation.SWImplementationContextFactory; @@ -38,6 +39,7 @@ import org.apache.skywalking.apm.agent.bytebuddy.SWAuxiliaryTypeNamingStrategy; import org.apache.skywalking.apm.agent.bytebuddy.SWClassFileLocator; import org.apache.skywalking.apm.agent.bytebuddy.biz.BizFoo; +import org.apache.skywalking.apm.agent.bytebuddy.biz.ChildBar; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.junit.Assert; import org.junit.BeforeClass; @@ -58,11 +60,15 @@ import static net.bytebuddy.jar.asm.Opcodes.ACC_PRIVATE; import static net.bytebuddy.jar.asm.Opcodes.ACC_VOLATILE; import static org.apache.skywalking.apm.agent.core.plugin.AbstractClassEnhancePluginDefine.CONTEXT_ATTR_NAME; +import static org.apache.skywalking.apm.agent.core.plugin.AbstractClassEnhancePluginDefine.CONTEXT_GETTER_NAME; +import static org.apache.skywalking.apm.agent.core.plugin.AbstractClassEnhancePluginDefine.CONTEXT_SETTER_NAME; public class AbstractInterceptTest { public static final String BIZ_FOO_CLASS_NAME = "org.apache.skywalking.apm.agent.bytebuddy.biz.BizFoo"; public static final String PROJECT_SERVICE_CLASS_NAME = "org.apache.skywalking.apm.agent.bytebuddy.biz.ProjectService"; public static final String DOC_SERVICE_CLASS_NAME = "org.apache.skywalking.apm.agent.bytebuddy.biz.DocService"; + public static final String PARENT_BAR_CLASS_NAME = "org.apache.skywalking.apm.agent.bytebuddy.biz.ParentBar"; + public static final String CHILD_BAR_CLASS_NAME = "org.apache.skywalking.apm.agent.bytebuddy.biz.ChildBar"; public static final String SAY_HELLO_METHOD = "sayHello"; public static final int BASE_INT_VALUE = 100; public static final String CONSTRUCTOR_INTERCEPTOR_CLASS = "constructorInterceptorClass"; @@ -85,6 +91,20 @@ protected void failed(Throwable e, Description description) { } }; + protected static void callBar(int round) { + Log.info("-------------"); + Log.info("callChildBar: " + round); + // load target class + String strResultChild = new ChildBar().sayHelloChild(); + Log.info("result: " + strResultChild); + + String strResultParent = new ChildBar().sayHelloParent(); + Log.info("result: " + strResultParent); + + Assert.assertEquals("String value is unexpected", "John", strResultChild); + Assert.assertEquals("String value is unexpected", "John", strResultParent); + } + protected static void callBizFoo(int round) { Log.info("-------------"); Log.info("callBizFoo: " + round); @@ -115,7 +135,7 @@ protected static void checkConstructorInterceptor(String className, int round) { protected static void checkInterface(Class testClass, Class interfaceCls) { Assert.assertTrue("Check interface failure, the test class: " + testClass + " does not implement the expected interface: " + interfaceCls, - EnhancedInstance.class.isAssignableFrom(BizFoo.class)); + EnhancedInstance.class.isAssignableFrom(testClass)); } protected static void checkErrors() { @@ -195,6 +215,9 @@ protected void installInterface(String className) { builder = builder.defineField( CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE) .implement(EnhancedInstance.class) + .defineMethod(CONTEXT_GETTER_NAME, Object.class, Visibility.PUBLIC) + .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME)) + .defineMethod(CONTEXT_SETTER_NAME, void.class, Visibility.PUBLIC).withParameters(Object.class) .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME)); } return builder; @@ -223,7 +246,7 @@ protected void installTraceClassTransformer(String msg) { ClassFileTransformer classFileTransformer = new ClassFileTransformer() { @Override public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - if (className.endsWith("BizFoo") || className.endsWith("ProjectService") || className.endsWith("DocService")) { + if (className.endsWith("BizFoo") || className.endsWith("ProjectService") || className.endsWith("DocService") || className.endsWith("ChildBar") || className.endsWith("ParentBar")) { Log.error(msg + className); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ClassReader cr = new ClassReader(classfileBuffer); diff --git a/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/cases/ReTransform4Test.java b/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/cases/ReTransform4Test.java new file mode 100644 index 0000000000..877dd416e7 --- /dev/null +++ b/apm-sniffer/bytebuddy-patch/src/test/java/org/apache/skywalking/apm/agent/bytebuddy/cases/ReTransform4Test.java @@ -0,0 +1,62 @@ +/* + * 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.agent.bytebuddy.cases; + +import net.bytebuddy.agent.ByteBuddyAgent; +import org.apache.skywalking.apm.agent.bytebuddy.biz.ChildBar; +import org.apache.skywalking.apm.agent.bytebuddy.biz.ParentBar; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.junit.Test; + +import java.lang.instrument.Instrumentation; + +public class ReTransform4Test extends AbstractReTransformTest { + + @Test + public void testInterceptConstructor() throws Exception { + Instrumentation instrumentation = ByteBuddyAgent.install(); + + // install transformer + installMethodInterceptor(PARENT_BAR_CLASS_NAME, "sayHelloParent", 1); + installMethodInterceptor(CHILD_BAR_CLASS_NAME, "sayHelloChild", 1); + // implement EnhancedInstance + installInterface(PARENT_BAR_CLASS_NAME); + installInterface(CHILD_BAR_CLASS_NAME); + + // call target class + callBar(1); + + // check interceptors + checkInterface(ParentBar.class, EnhancedInstance.class); + checkInterface(ChildBar.class, EnhancedInstance.class); + checkErrors(); + + installTraceClassTransformer("Trace class: "); + + // do retransform + reTransform(instrumentation, ChildBar.class); + + // check interceptors + checkInterface(ParentBar.class, EnhancedInstance.class); + checkInterface(ChildBar.class, EnhancedInstance.class); + checkErrors(); + } + +} + From 6c74815fdf5facd958faf95de52ee5327da66119 Mon Sep 17 00:00:00 2001 From: saber-wang <45062099+saber-wang@users.noreply.github.com> Date: Tue, 10 Jun 2025 11:59:05 +0800 Subject: [PATCH 063/114] Add support for dameng(DM) JDBC URL format in URLParser (#758) * [Feature] Add URLParser for dameng(DM) --- CHANGES.md | 1 + .../trace/component/ComponentsDefine.java | 3 + .../connectionurl/parser/DMURLParser.java | 112 ++++++++++++++++++ .../jdbc/connectionurl/parser/URLParser.java | 4 + .../connectionurl/parser/URLParserTest.java | 45 +++++++ .../java-agent/Supported-list.md | 1 + 6 files changed, 166 insertions(+) create mode 100644 apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/DMURLParser.java diff --git a/CHANGES.md b/CHANGES.md index 8e58c3459d..eea1320db7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ Release Notes. initialization. Delay so11y metrics#build when the services are not ready to avoid MeterService status is not initialized. * Fix retransform failure when enhancing both parent and child classes. +* Add support for `dameng(DM)` JDBC url format in `URLParser`. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index d81ba8c136..fa62c91239 100755 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -262,4 +262,7 @@ public class ComponentsDefine { public static final OfficialComponent CAFFEINE = new OfficialComponent(160, "Caffeine"); public static final OfficialComponent THREAD_PER_TASK_EXECUTOR = new OfficialComponent(161, "ThreadPerTask-executor"); + + public static final OfficialComponent DMDB_JDBC_DRIVER = new OfficialComponent(163, "Dmdb-jdbc-driver"); + } diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/DMURLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/DMURLParser.java new file mode 100644 index 0000000000..2cb4c1c4c0 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/DMURLParser.java @@ -0,0 +1,112 @@ +/* + * 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.jdbc.connectionurl.parser; + +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +public class DMURLParser extends AbstractURLParser { + private static final int DEFAULT_PORT = 5236; + private static final String DB_TYPE = "DM"; + private static final String URL_PARAMS_HOST_KEY = "host"; + private static final String URL_PARAMS_PORT_KEY = "port"; + private static final String URL_PARAMS_SCHEMA_KEY = "schema"; + + public DMURLParser(String url) { + super(url); + } + + @Override + protected URLLocation fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("//"); + if (hostLabelStartIndex == -1) { + return new URLLocation(0, 0); + } + int hostLabelEndIndex = url.indexOf("?", hostLabelStartIndex + 2); + if (hostLabelEndIndex == -1) { + hostLabelEndIndex = url.length(); + } + return new URLLocation(hostLabelStartIndex + 2, hostLabelEndIndex); + } + + @Override + protected URLLocation fetchDatabaseNameIndexRange() { + return new URLLocation(0, 0); + } + + @Override + public ConnectionInfo parse() { + URLLocation location = fetchDatabaseHostsIndexRange(); + String hostPortSegment = ""; + if (location.endIndex() > location.startIndex()) { + hostPortSegment = url.substring(location.startIndex(), location.endIndex()); + } + + String host = ""; + String port = ""; + + if (!hostPortSegment.isEmpty()) { + String[] parts = hostPortSegment.split(":"); + if (parts.length >= 1) { + host = parts[0]; + } + if (parts.length == 2) { + port = parts[1]; + } + } + + if (host.isEmpty()) { + host = fetchFromUrlParams(URL_PARAMS_HOST_KEY); + } + if (port == null || port.isEmpty()) { + port = fetchFromUrlParams(URL_PARAMS_PORT_KEY); + } + + if (port == null || port.isEmpty()) { + port = String.valueOf(DEFAULT_PORT); + } + + String schema = fetchFromUrlParams(URL_PARAMS_SCHEMA_KEY); + + return new ConnectionInfo( + ComponentsDefine.DMDB_JDBC_DRIVER, + DB_TYPE, + host, + Integer.parseInt(port), + schema == null ? "" : schema + ); + } + + private String fetchFromUrlParams(String key) { + int paramIndex = url.indexOf("?"); + if (paramIndex == -1) { + return null; + } + String[] params = url.substring(paramIndex + 1).split("&"); + for (String pair : params) { + if (pair.startsWith(key + "=")) { + String[] segments = pair.split("=", 2); + if (segments.length == 2) { + return segments[1]; + } + } + } + return null; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java index cb79d58b0c..83afcf9efa 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParser.java @@ -41,6 +41,7 @@ public class URLParser { private static final String DB2_JDBC_URL_PREFIIX = "jdbc:db2:"; private static final String SYBASE_JDBC_URL_PREFIX = "jdbc:sybase:tds:"; private static final String OCEANBASE_JDBC_URL_PREFIX = "jdbc:oceanbase:"; + private static final String DM_JDBC_URL_PREFIX = "jdbc:dm:"; public static ConnectionInfo parser(String url) { ConnectionURLParser parser = null; @@ -75,7 +76,10 @@ public static ConnectionInfo parser(String url) { parser = new SybaseURLParser(url); } else if (lowerCaseUrl.startsWith(OCEANBASE_JDBC_URL_PREFIX)) { parser = new OceanBaseURLParser(url); + } else if (lowerCaseUrl.startsWith(DM_JDBC_URL_PREFIX)) { + parser = new DMURLParser(url); } + return parser.parse(); } } diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java index 2a0e87e315..a9a38450e0 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/test/java/org/apache/skywalking/apm/plugin/jdbc/connectionurl/parser/URLParserTest.java @@ -415,4 +415,49 @@ public void testParseSybaseJDBCURL() { assertThat(connectionInfo.getDatabaseName(), is("mydb")); assertThat(connectionInfo.getDatabasePeer(), is("localhost:5000")); } + + @Test + public void testParseDMJDBCURLWithNamedParams() + { + ConnectionInfo connectionInfo = URLParser.parser("jdbc:dm://?host=localhost&port=5236"); + assertThat(connectionInfo.getDBType(), is("DM")); + assertThat(connectionInfo.getDatabaseName(), is("")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:5236")); + } + + @Test + public void testParseDMJDBCURLWithNamedParamsAndScheme() + { + ConnectionInfo connectionInfo = URLParser.parser("jdbc:dm://?host=localhost&port=5236&schema=dm"); + assertThat(connectionInfo.getDBType(), is("DM")); + assertThat(connectionInfo.getDatabaseName(), is("dm")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:5236")); + } + + @Test + public void testParseDMJDBCURLWithoutHost() + { + ConnectionInfo connectionInfo = URLParser.parser("jdbc:dm://localhost"); + assertThat(connectionInfo.getDBType(), is("DM")); + assertThat(connectionInfo.getDatabaseName(), is("")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:5236")); + } + + @Test + public void testParseDMJDBCURLWithoutHostAndScheme() + { + ConnectionInfo connectionInfo = URLParser.parser("jdbc:dm://localhost?schema=dm"); + assertThat(connectionInfo.getDBType(), is("DM")); + assertThat(connectionInfo.getDatabaseName(), is("dm")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:5236")); + } + + @Test + public void testParseDMJDBCURLWithoutHostPort() + { + ConnectionInfo connectionInfo = URLParser.parser("jdbc:dm://localhost:5237?schema=dm"); + assertThat(connectionInfo.getDBType(), is("DM")); + assertThat(connectionInfo.getDatabaseName(), is("dm")); + assertThat(connectionInfo.getDatabasePeer(), is("localhost:5237")); + } } diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index cd51b8d2ce..caf406d960 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -185,6 +185,7 @@ The meter plugin provides the advanced metrics collections, which are not a part * [DB2](https://www.ibm.com/products/db2/database) * Sybase * [OceanBase](https://www.oceanbase.com/) + * [DaMeng(DM)](https://www.dameng.com/) * Supported Connection Pool Frameworks * [Apache Commons DBCP](https://github.com/apache/commons-dbcp) 2.x * [Alibaba Druid](https://github.com/alibaba/druid) 1.x From 7f9287fcb189048acd8d9ce8ab5687664ee150e0 Mon Sep 17 00:00:00 2001 From: ayue Date: Sat, 21 Jun 2025 12:20:28 +0800 Subject: [PATCH 064/114] Fix: RabbitMQ Consumer could not receive handleCancelOk callback(#13334) (#759) Signed-off-by: ayue --- CHANGES.md | 1 + .../apache/skywalking/apm/plugin/rabbitmq/TracerConsumer.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index eea1320db7..0a846a2630 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,7 @@ Release Notes. initialized. * Fix retransform failure when enhancing both parent and child classes. * Add support for `dameng(DM)` JDBC url format in `URLParser`. +* Fix RabbitMQ Consumer could not receive handleCancelOk callback. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/rabbitmq/TracerConsumer.java b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/rabbitmq/TracerConsumer.java index bb6f134fca..c3ae14470e 100644 --- a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/rabbitmq/TracerConsumer.java +++ b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/rabbitmq/TracerConsumer.java @@ -50,7 +50,7 @@ public void handleConsumeOk(final String consumerTag) { @Override public void handleCancelOk(final String consumerTag) { - this.delegate.handleRecoverOk(consumerTag); + this.delegate.handleCancelOk(consumerTag); } @Override From b1f18f36ba45177ffcefbc13c7a6b030445cccba Mon Sep 17 00:00:00 2001 From: "changhao.ni" <35791621+nichanghao@users.noreply.github.com> Date: Wed, 25 Jun 2025 11:41:46 +0800 Subject: [PATCH 065/114] Feature: Support for tracking for lettuce versions 6.5+ (#760) --- .github/workflows/plugins-test.1.yaml | 1 + CHANGES.md | 1 + .../lettuce-5.x-6.4.x-plugin/pom.xml | 55 +++++++ .../v5/RedisChannelWriterInterceptorV5.java | 29 ++++ .../RedisChannelWriterInstrumentationV5.java} | 27 ++-- .../src/main/resources/skywalking-plugin.def | 4 +- .../lettuce-6.5.x-plugin/pom.xml | 55 +++++++ .../v65/RedisChannelWriterInterceptorV65.java | 29 ++++ .../RedisChannelWriterInstrumentationV65.java | 82 +++++++++++ .../src/main/resources/skywalking-plugin.def | 17 +++ .../lettuce-common}/pom.xml | 13 +- ...faultEndpointChannelActiveInterceptor.java | 2 +- .../lettuce/common}/LettucePluginConfig.java | 2 +- .../RedisChannelWriterInterceptor.java | 11 +- .../RedisCommandCancelMethodInterceptor.java | 2 +- ...ompleteExceptionallyMethodInterceptor.java | 2 +- ...RedisCommandCompleteMethodInterceptor.java | 2 +- .../DefaultEndpointInstrumentation.java | 4 +- .../define/RedisCommandInstrumentation.java | 8 +- .../src/main/resources/skywalking-plugin.def | 18 +++ .../RedisChannelWriterInterceptorTest.java | 4 +- .../apm-sdk-plugin/lettuce-plugins/pom.xml | 39 +++++ apm-sniffer/apm-sdk-plugin/pom.xml | 2 +- .../service-agent/java-agent/Plugin-list.md | 4 +- .../java-agent/Supported-list.md | 2 +- .../lettuce-6.5.x-scenario/bin/startup.sh | 21 +++ .../config/expectedData.yaml | 101 +++++++++++++ .../lettuce-6.5.x-scenario/configuration.yml | 28 ++++ .../scenarios/lettuce-6.5.x-scenario/pom.xml | 136 ++++++++++++++++++ .../src/main/assembly/assembly.xml | 41 ++++++ .../apm/testcase/lettuce/Application.java | 30 ++++ .../lettuce/controller/LettuceController.java | 72 ++++++++++ .../src/main/resources/application.properties | 19 +++ .../src/main/resources/log4j2.xml | 30 ++++ .../support-version.list | 20 +++ .../lettuce-scenario/support-version.list | 3 +- 36 files changed, 877 insertions(+), 39 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorV5.java rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentation.java => lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentationV5.java} (81%) rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin => lettuce-plugins/lettuce-5.x-6.4.x-plugin}/src/main/resources/skywalking-plugin.def (73%) create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisChannelWriterInterceptorV65.java create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisChannelWriterInstrumentationV65.java create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin => lettuce-plugins/lettuce-common}/pom.xml (77%) rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5 => lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common}/DefaultEndpointChannelActiveInterceptor.java (97%) rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5 => lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common}/LettucePluginConfig.java (99%) rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5 => lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common}/RedisChannelWriterInterceptor.java (95%) rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5 => lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common}/RedisCommandCancelMethodInterceptor.java (97%) rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5 => lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common}/RedisCommandCompleteExceptionallyMethodInterceptor.java (97%) rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5 => lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common}/RedisCommandCompleteMethodInterceptor.java (97%) rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5 => lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common}/define/DefaultEndpointInstrumentation.java (94%) rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5 => lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common}/define/RedisCommandInstrumentation.java (92%) create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def rename apm-sniffer/apm-sdk-plugin/{lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5 => lettuce-plugins/lettuce-common/src/test/java/org/apache/skywalking/apm/plugin/lettuce/common}/RedisChannelWriterInterceptorTest.java (99%) create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/resources/application.properties create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/lettuce-6.5.x-scenario/support-version.list diff --git a/.github/workflows/plugins-test.1.yaml b/.github/workflows/plugins-test.1.yaml index e271ad915b..2c012792fc 100644 --- a/.github/workflows/plugins-test.1.yaml +++ b/.github/workflows/plugins-test.1.yaml @@ -72,6 +72,7 @@ jobs: - kafka-scenario - kotlin-coroutine-scenario - lettuce-scenario + - lettuce-6.5.x-scenario - mongodb-3.x-scenario - mongodb-4.x-scenario - netty-socketio-scenario diff --git a/CHANGES.md b/CHANGES.md index 0a846a2630..dbcd33a7f1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ Release Notes. * Fix retransform failure when enhancing both parent and child classes. * Add support for `dameng(DM)` JDBC url format in `URLParser`. * Fix RabbitMQ Consumer could not receive handleCancelOk callback. +* Support for tracking in lettuce versions 6.5.x and above. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml new file mode 100644 index 0000000000..538e68074c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml @@ -0,0 +1,55 @@ + + + + + 4.0.0 + + org.apache.skywalking + lettuce-plugins + 9.5.0-SNAPSHOT + + + apm-lettuce-5.x-6.4.x-plugin + jar + + lettuce-5.x-6.4.x-plugin + + + 5.0.0.RELEASE + + + + + org.apache.skywalking + apm-lettuce-common + ${project.version} + provided + + + + io.lettuce + lettuce-core + ${lettuce-core.version} + provided + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorV5.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorV5.java new file mode 100644 index 0000000000..d4984d6fd0 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorV5.java @@ -0,0 +1,29 @@ +/* + * 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.lettuce.v5; + +import io.lettuce.core.protocol.ProtocolKeyword; +import org.apache.skywalking.apm.plugin.lettuce.common.RedisChannelWriterInterceptor; + +public class RedisChannelWriterInterceptorV5 extends RedisChannelWriterInterceptor { + @Override + protected String getCommandName(final ProtocolKeyword protocol) { + return protocol.name(); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentationV5.java similarity index 81% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentationV5.java index e0a4d8c819..bf3e52f79c 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentationV5.java @@ -18,27 +18,26 @@ package org.apache.skywalking.apm.plugin.lettuce.v5.define; +import java.util.Collections; +import java.util.List; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; 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 java.util.List; - import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import static org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch; -/** - * The writeAndFlush method is used in versions lower than 5.0.2.RELEASE - */ -public class RedisChannelWriterInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { +public class RedisChannelWriterInstrumentationV5 extends ClassInstanceMethodsEnhancePluginDefine { private static final String ENHANCE_CLASS = "io.lettuce.core.RedisChannelWriter"; - private static final String REDIS_CHANNEL_WRITER_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.lettuce.v5.RedisChannelWriterInterceptor"; + private static final String REDIS_CHANNEL_WRITER_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.lettuce.v5.RedisChannelWriterInterceptorV5"; @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { @@ -47,12 +46,12 @@ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { @Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{ + return new InstanceMethodsInterceptPoint[] { new InstanceMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { return named("write").and(takesArgument(0, named("io.lettuce.core.protocol.RedisCommand")).or( - takesArgument(0, List.class))); + takesArgument(0, List.class))); } @Override @@ -65,11 +64,19 @@ public boolean isOverrideArgs() { return false; } }, - }; + }; } @Override public ClassMatch enhanceClass() { return byHierarchyMatch(ENHANCE_CLASS); } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + "io.lettuce.core.protocol.ProtocolKeyword", + ElementMatchers.named("name") + )); + } } diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def similarity index 73% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/resources/skywalking-plugin.def rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def index bea812747c..1ff563829d 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def @@ -14,6 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -lettuce-5.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.DefaultEndpointInstrumentation -lettuce-5.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisChannelWriterInstrumentation -lettuce-5.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisCommandInstrumentation \ No newline at end of file +lettuce-5.x-6.4.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisChannelWriterInstrumentationV5 \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml new file mode 100644 index 0000000000..d962ade037 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml @@ -0,0 +1,55 @@ + + + + + 4.0.0 + + org.apache.skywalking + lettuce-plugins + 9.5.0-SNAPSHOT + + apm-lettuce-6.5.x-plugin + + jar + + lettuce-6.5.x-plugin + + + 6.5.0.RELEASE + + + + + org.apache.skywalking + apm-lettuce-common + ${project.version} + provided + + + + io.lettuce + lettuce-core + ${lettuce-core.version} + provided + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisChannelWriterInterceptorV65.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisChannelWriterInterceptorV65.java new file mode 100644 index 0000000000..2205fa3519 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisChannelWriterInterceptorV65.java @@ -0,0 +1,29 @@ +/* + * 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.lettuce.v65; + +import io.lettuce.core.protocol.ProtocolKeyword; +import org.apache.skywalking.apm.plugin.lettuce.common.RedisChannelWriterInterceptor; + +public class RedisChannelWriterInterceptorV65 extends RedisChannelWriterInterceptor { + @Override + protected String getCommandName(final ProtocolKeyword protocol) { + return protocol.toString(); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisChannelWriterInstrumentationV65.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisChannelWriterInstrumentationV65.java new file mode 100644 index 0000000000..5e10c43561 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisChannelWriterInstrumentationV65.java @@ -0,0 +1,82 @@ +/* + * 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.lettuce.v65.define; + +import java.util.Collections; +import java.util.List; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; +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.takesArgument; +import static org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch; + +public class RedisChannelWriterInstrumentationV65 extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "io.lettuce.core.RedisChannelWriter"; + + private static final String REDIS_CHANNEL_WRITER_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.lettuce.v65.RedisChannelWriterInterceptorV65"; + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("write").and(takesArgument(0, named("io.lettuce.core.protocol.RedisCommand")).or( + takesArgument(0, List.class))); + } + + @Override + public String getMethodsInterceptor() { + return REDIS_CHANNEL_WRITER_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + }; + } + + @Override + public ClassMatch enhanceClass() { + return byHierarchyMatch(ENHANCE_CLASS); + } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + "io.lettuce.core.protocol.ProtocolKeyword", + ElementMatchers.named("toString") + )); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..a503891244 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-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. + +lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65 \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml similarity index 77% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml index 05b0f3a44f..142e7f4541 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml @@ -1,4 +1,4 @@ - + - + 4.0.0 org.apache.skywalking - apm-sdk-plugin + lettuce-plugins 9.5.0-SNAPSHOT - apm-lettuce-5.x-plugin + apm-lettuce-common jar - lettuce-5.x-plugin - http://maven.apache.org 5.1.3.RELEASE @@ -42,4 +42,5 @@ provided + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/DefaultEndpointChannelActiveInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/DefaultEndpointChannelActiveInterceptor.java similarity index 97% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/DefaultEndpointChannelActiveInterceptor.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/DefaultEndpointChannelActiveInterceptor.java index f536d1770e..f8f63e3da3 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/DefaultEndpointChannelActiveInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/DefaultEndpointChannelActiveInterceptor.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5; +package org.apache.skywalking.apm.plugin.lettuce.common; import io.netty.channel.Channel; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/LettucePluginConfig.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/LettucePluginConfig.java similarity index 99% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/LettucePluginConfig.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/LettucePluginConfig.java index a20ca1cb45..b64afea453 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/LettucePluginConfig.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/LettucePluginConfig.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5; +package org.apache.skywalking.apm.plugin.lettuce.common; import org.apache.skywalking.apm.agent.core.boot.PluginConfig; diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java similarity index 95% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptor.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java index c1d731e435..f8b66f1349 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java @@ -16,11 +16,12 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5; +package org.apache.skywalking.apm.plugin.lettuce.common; import io.lettuce.core.codec.StringCodec; import io.lettuce.core.protocol.CommandArgs; import io.lettuce.core.protocol.DecoratedCommand; +import io.lettuce.core.protocol.ProtocolKeyword; import io.lettuce.core.protocol.RedisCommand; import org.apache.skywalking.apm.agent.core.conf.Constants; import org.apache.skywalking.apm.agent.core.context.ContextManager; @@ -71,7 +72,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr String command = Constants.EMPTY_STRING; if (allArguments[0] instanceof RedisCommand) { RedisCommand redisCommand = (RedisCommand) allArguments[0]; - command = redisCommand.getType().name(); + command = getCommandName(redisCommand.getType()); operationName = operationName + command; if (LettucePluginConfig.Plugin.Lettuce.TRACE_REDIS_PARAMETERS) { key = getArgsKey(redisCommand); @@ -95,7 +96,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } private String getArgsKey(RedisCommand redisCommand) { - if (AUTH.equalsIgnoreCase(redisCommand.getType().name())) { + if (AUTH.equalsIgnoreCase(getCommandName(redisCommand.getType()))) { return PASSWORD_MASK; } CommandArgs args = redisCommand.getArgs(); @@ -130,6 +131,10 @@ public void handleMethodException(EnhancedInstance objInst, Method method, Objec } } + protected String getCommandName(ProtocolKeyword protocol) { + return "UNKNOWN"; + } + private static RedisCommand getSpanCarrierCommand(Object o) { RedisCommand command = null; if (o instanceof RedisCommand) { diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisCommandCancelMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java similarity index 97% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisCommandCancelMethodInterceptor.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java index c6d4969563..7fb9f3c943 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisCommandCancelMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5; +package org.apache.skywalking.apm.plugin.lettuce.common; import org.apache.skywalking.apm.agent.core.context.tag.StringTag; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisCommandCompleteExceptionallyMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java similarity index 97% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisCommandCompleteExceptionallyMethodInterceptor.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java index 46c0323999..bdde0712df 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisCommandCompleteExceptionallyMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5; +package org.apache.skywalking.apm.plugin.lettuce.common; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisCommandCompleteMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java similarity index 97% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisCommandCompleteMethodInterceptor.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java index f59c3074b4..d2ede33ba7 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisCommandCompleteMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5; +package org.apache.skywalking.apm.plugin.lettuce.common; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/DefaultEndpointInstrumentation.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/DefaultEndpointInstrumentation.java similarity index 94% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/DefaultEndpointInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/DefaultEndpointInstrumentation.java index 9ec114fdf9..731d4aa094 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/DefaultEndpointInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/DefaultEndpointInstrumentation.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5.define; +package org.apache.skywalking.apm.plugin.lettuce.common.define; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -33,7 +33,7 @@ public class DefaultEndpointInstrumentation extends ClassInstanceMethodsEnhanceP private static final String ENHANCE_CLASS = "io.lettuce.core.protocol.DefaultEndpoint"; - private static final String DEFAULT_ENDPOINT_CHANNEL_ACTIVE_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.v5.DefaultEndpointChannelActiveInterceptor"; + private static final String DEFAULT_ENDPOINT_CHANNEL_ACTIVE_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.common.DefaultEndpointChannelActiveInterceptor"; @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisCommandInstrumentation.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisCommandInstrumentation.java similarity index 92% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisCommandInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisCommandInstrumentation.java index 87dfc48712..c7caec6006 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisCommandInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisCommandInstrumentation.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5.define; +package org.apache.skywalking.apm.plugin.lettuce.common.define; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -34,9 +34,9 @@ public class RedisCommandInstrumentation extends ClassInstanceMethodsEnhancePlug private static final String ENHANCE_CLASS = "io.lettuce.core.protocol.RedisCommand"; - private static final String REDIS_COMMAND_COMPLETE_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.v5.RedisCommandCompleteMethodInterceptor"; - private static final String REDIS_COMMAND_COMPLETE_EXCEPTIONALLY_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.v5.RedisCommandCompleteExceptionallyMethodInterceptor"; - public static final String REDIS_COMMAND_CANCEL_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.v5.RedisCommandCancelMethodInterceptor"; + private static final String REDIS_COMMAND_COMPLETE_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.common.RedisCommandCompleteMethodInterceptor"; + private static final String REDIS_COMMAND_COMPLETE_EXCEPTIONALLY_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.common.RedisCommandCompleteExceptionallyMethodInterceptor"; + public static final String REDIS_COMMAND_CANCEL_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.common.RedisCommandCancelMethodInterceptor"; @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..e0521938a7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def @@ -0,0 +1,18 @@ +# 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. + +lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.DefaultEndpointInstrumentation +lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.RedisCommandInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/test/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptorTest.java similarity index 99% rename from apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java rename to apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/test/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptorTest.java index 190667d0ca..db63ef9cf4 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/test/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptorTest.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.lettuce.v5; +package org.apache.skywalking.apm.plugin.lettuce.common; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -132,7 +132,7 @@ public void testInterceptor() { List spans = SegmentHelper.getSpans(traceSegment); assertNotNull(spans); assertThat(spans.size(), is(1)); - assertThat(spans.get(0).getOperationName(), is("Lettuce/SET")); + assertThat(spans.get(0).getOperationName(), is("Lettuce/UNKNOWN")); assertThat(spans.get(0).isExit(), is(true)); assertThat(SpanHelper.getComponentId(spans.get(0)), is(57)); List tags = SpanHelper.getTags(spans.get(0)); diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml new file mode 100644 index 0000000000..aba6387406 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml @@ -0,0 +1,39 @@ + + + + + 4.0.0 + + org.apache.skywalking + apm-sdk-plugin + 9.5.0-SNAPSHOT + + + lettuce-plugins + pom + + + lettuce-common + lettuce-5.x-6.4.x-plugin + lettuce-6.5.x-plugin + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index cd92e19f81..6c6c30c9d6 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -87,7 +87,7 @@ netty-socketio-plugin httpclient-3.x-plugin play-2.x-plugin - lettuce-5.x-plugin + lettuce-plugins avro-plugin finagle-6.25.x-plugin quasar-plugin 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 aa85d4bcb2..58a3a50ffc 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -57,7 +57,9 @@ - kafka-0.11.x/1.x/2.x - kafka-3.7.x - kotlin-coroutine -- lettuce-5.x +- lettuce-common +- lettuce-5.x-6.4.x +- lettuce-6.5.x - light4j - mariadb-2.x - micrometer-1.10.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index caf406d960..46db6647c8 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -89,7 +89,7 @@ metrics based on the tracing data. * Redis * [Jedis](https://github.com/xetorthio/jedis) 2.x-4.x * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 3.5.0 -> 3.30.0 - * [Lettuce](https://github.com/lettuce-io/lettuce-core) 5.x + * [Lettuce](https://github.com/lettuce-io/lettuce-core) 5.x -> 6.7.1 * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14, 3.4.0-3.12.7, 4.0.0-4.1.0 * Memcached Client * [Spymemcached](https://github.com/couchbase/spymemcached) 2.x diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/bin/startup.sh b/test/plugin/scenarios/lettuce-6.5.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..3ef5c866ff --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-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 -Dredis.host=${REDIS_SERVERS} -jar -Dskywalking.plugin.lettuce.trace_redis_parameters=true ${agent_opts} ${home}/../libs/lettuce-6.5.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..2a938caea9 --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml @@ -0,0 +1,101 @@ +# 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: lettuce-6.5.x-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: HEAD:/lettuce-6.5.x-scenario/case/healthCheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/lettuce-6.5.x-scenario/case/healthCheck'} + - {key: http.method, value: HEAD} + - {key: http.status_code, value: '200'} + - segmentId: not null + spans: + - operationName: Lettuce/GET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: cache.type, value: Redis} + - {key: cache.key, value: key} + - {key: cache.cmd, value: GET} + - {key: cache.op, value: read} + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key0 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 3 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key1 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: GET:/lettuce-6.5.x-scenario/case/lettuce-case + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/lettuce-6.5.x-scenario/case/lettuce-case'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/configuration.yml b/test/plugin/scenarios/lettuce-6.5.x-scenario/configuration.yml new file mode 100644 index 0000000000..6ddf05ae02 --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/configuration.yml @@ -0,0 +1,28 @@ +# 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/lettuce-6.5.x-scenario/case/lettuce-case +healthCheck: http://localhost:8080/lettuce-6.5.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: + - REDIS_SERVERS=redis-server:6379 +depends_on: + - redis-server +dependencies: + redis-server: + image: redis:3.2.9-alpine + hostname: redis-server diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/pom.xml b/test/plugin/scenarios/lettuce-6.5.x-scenario/pom.xml new file mode 100644 index 0000000000..248aded74a --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/pom.xml @@ -0,0 +1,136 @@ + + + + 4.0.0 + + org.apache.skywalking + lettuce-6.5.x-scenario + 1.0.0 + + + UTF-8 + 1.8 + 3.8.1 + 6.5.0.RELEASE + ${test.framework.version} + 2.6.2 + 4.3.8.RELEASE + 2.1.6.RELEASE + 3.4.2 + + + lettuce-6.5.x-scenario + + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + + io.lettuce + lettuce-core + ${test.framework.version} + + + + org.springframework.boot + spring-boot-starter + ${spring.boot.version} + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j.version} + + + org.apache.logging.log4j + log4j-jcl + ${log4j.version} + + + org.springframework.boot + spring-boot-starter-tomcat + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + + + lettuce-6.5.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${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/lettuce-6.5.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..a48d54c644 --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/lettuce-6.5.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java new file mode 100644 index 0000000000..f96b624013 --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java @@ -0,0 +1,30 @@ +/* + * 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.testcase.lettuce; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java new file mode 100644 index 0000000000..c2f391b07c --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java @@ -0,0 +1,72 @@ +/* + * 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.testcase.lettuce.controller; + +import io.lettuce.core.LettuceFutures; +import io.lettuce.core.RedisClient; +import io.lettuce.core.RedisFuture; +import io.lettuce.core.api.StatefulRedisConnection; +import io.lettuce.core.api.async.RedisAsyncCommands; +import io.lettuce.core.api.sync.RedisCommands; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +@RequestMapping("/case") +@PropertySource("classpath:application.properties") +public class LettuceController { + + @Value("${redis.servers:127.0.0.1:6379}") + private String address; + + @RequestMapping("/lettuce-case") + @ResponseBody + public String lettuceCase() { + RedisClient redisClient = RedisClient.create("redis://" + address); + StatefulRedisConnection connection0 = redisClient.connect(); + RedisCommands syncCommand = connection0.sync(); + syncCommand.get("key"); + + StatefulRedisConnection connection1 = redisClient.connect(); + RedisAsyncCommands asyncCommands = connection1.async(); + asyncCommands.setAutoFlushCommands(false); + List> futures = new ArrayList<>(); + futures.add(asyncCommands.set("key0", "value0")); + futures.add(asyncCommands.set("key1", "value1")); + asyncCommands.flushCommands(); + LettuceFutures.awaitAll(5, TimeUnit.SECONDS, futures.toArray(new RedisFuture[futures.size()])); + + connection0.close(); + connection1.close(); + redisClient.shutdown(); + return "Success"; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + return "healthCheck"; + } +} diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/resources/application.properties b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/resources/application.properties new file mode 100644 index 0000000000..0b168c7fdd --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/resources/application.properties @@ -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 +server.servlet.context-path=/lettuce-6.5.x-scenario \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/support-version.list b/test/plugin/scenarios/lettuce-6.5.x-scenario/support-version.list new file mode 100644 index 0000000000..df1aa5eb09 --- /dev/null +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/support-version.list @@ -0,0 +1,20 @@ +# 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. + +6.5.0.RELEASE +6.5.5.RELEASE +6.6.0.RELEASE +6.7.1.RELEASE \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-scenario/support-version.list b/test/plugin/scenarios/lettuce-scenario/support-version.list index add9033ee2..88e41e9ab3 100644 --- a/test/plugin/scenarios/lettuce-scenario/support-version.list +++ b/test/plugin/scenarios/lettuce-scenario/support-version.list @@ -17,4 +17,5 @@ 5.2.1.RELEASE 5.1.8.RELEASE 5.0.5.RELEASE -6.1.4.RELEASE \ No newline at end of file +6.1.4.RELEASE +6.4.2.RELEASE \ No newline at end of file From b7139d6b80e996bc410749c3ac4315f762a58a59 Mon Sep 17 00:00:00 2001 From: lhl <46373026+KeekLove@users.noreply.github.com> Date: Sat, 28 Jun 2025 22:49:43 +0800 Subject: [PATCH 066/114] Upgrade bytebuddy to 1.17.6 (#761) --- CHANGES.md | 1 + apm-sniffer/apm-agent/pom.xml | 1 + dist-material/LICENSE | 2 +- pom.xml | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dbcd33a7f1..57df5dde95 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ Release Notes. * Add support for `dameng(DM)` JDBC url format in `URLParser`. * Fix RabbitMQ Consumer could not receive handleCancelOk callback. * Support for tracking in lettuce versions 6.5.x and above. +* Upgrade byte-buddy version to 1.17.6. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 6454eed897..9429528a9b 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -106,6 +106,7 @@ net.bytebuddy:byte-buddy META-INF/versions/9/module-info.class + META-INF/versions/24/** diff --git a/dist-material/LICENSE b/dist-material/LICENSE index d763acd590..e261fd20da 100755 --- a/dist-material/LICENSE +++ b/dist-material/LICENSE @@ -215,7 +215,7 @@ Apache 2.0 licenses The following components are provided under the Apache License. See project link for details. The text of each license is the standard Apache 2.0 license. - raphw (byte-buddy) 1.14.9: http://bytebuddy.net/ , Apache 2.0 + raphw (byte-buddy) 1.17.6: http://bytebuddy.net/ , Apache 2.0 Google: grpc-java 1.68.1: https://github.com/grpc/grpc-java, Apache 2.0 Google: gson 2.8.9: https://github.com/google/gson , Apache 2.0 Google: proto-google-common-protos 2.0.1: https://github.com/googleapis/googleapis , Apache 2.0 diff --git a/pom.xml b/pom.xml index 1e546b07f4..128d7f6f00 100755 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ 1.18.30 - 1.14.9 + 1.17.6 1.68.1 4.1.115.Final 2.8.9 From eec41328ddf40ead89dd2f16f65b27a9db888351 Mon Sep 17 00:00:00 2001 From: Wan Kai Date: Thu, 17 Jul 2025 22:04:28 +0800 Subject: [PATCH 067/114] docs: Add Couchbase Java SDK to supported list (#763) --- .../service-agent/java-agent/Supported-list.md | 13 +++++++------ .../service-agent/java-agent/configurations.md | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 46db6647c8..23c5680cd3 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -12,10 +12,10 @@ metrics based on the tracing data. * Spring MVC 6.x (Optional²) * [Nutz Web Framework](https://github.com/nutzam/nutz) 1.x * [Struts2 MVC](http://struts.apache.org/) 2.3.x -> 2.5.x - * Resin 3 (Optional¹) - * Resin 4 (Optional¹) + * Resin 3 (Optional¹), See [SkySPM Plugin Repository](https://github.com/SkyAPM/java-plugin-extensions) + * Resin 4 (Optional¹), See [SkySPM Plugin Repository](https://github.com/SkyAPM/java-plugin-extensions) * [Jetty Server](http://www.eclipse.org/jetty/) 9.x -> 11.x - * [Spring WebFlux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) 5.x (Optional¹) -> 6.x (Optional¹) + * [Spring WebFlux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) 5.x (Optional²) -> 6.x (Optional²) * [Undertow](http://undertow.io/) 1.3.0.Final -> 2.0.27.Final * [RESTEasy](https://resteasy.dev/) 3.1.0.Final -> 6.2.4.Final * [Play Framework](https://www.playframework.com/) 2.6.x -> 2.8.x @@ -46,7 +46,7 @@ metrics based on the tracing data. * [Apache ShenYu](https://shenyu.apache.org) (Rich protocol support: `HTTP`,`Spring Cloud`,`gRPC`,`Dubbo`,`SOFARPC`,`Motan`,`Tars`) 2.4.x (Optional²) * JDBC * Mysql Driver 5.x, 6.x, 8.x - * Oracle Driver (Optional¹) + * Oracle Driver (Optional¹), See [SkySPM Plugin Repository](https://github.com/SkyAPM/java-plugin-extensions) * H2 Driver 1.3.x -> 1.4.x * [ShardingSphere](https://github.com/apache/shardingsphere) 3.0.0, 4.0.0, 4.0.1, 4.1.0, 4.1.1, 5.0.0 * PostgreSQL Driver 8.x, 9.x, 42.x @@ -83,7 +83,7 @@ metrics based on the tracing data. * [Pulsar](http://pulsar.apache.org) 2.2.x -> 2.9.x * [NATS](https://github.com/nats-io/nats.java) 2.14.x -> 2.16.5 * [ActiveMQ-Artemis](https://github.com/apache/activemq) 2.30.0 -> 2.31.2 - * Aliyun ONS 1.x (Optional¹) + * Aliyun ONS 1.x (Optional¹), See [SkySPM Plugin Repository](https://github.com/SkyAPM/java-plugin-extensions) * NoSQL * [aerospike](https://github.com/aerospike/aerospike-client-java) 3.x -> 6.x * Redis @@ -108,6 +108,7 @@ metrics based on the tracing data. * [hbase-client](https://github.com/apache/hbase) HTable 1.0.0-2.4.2 * Neo4j * [Neo4j-java](https://neo4j.com/docs/java-manual/current/) 4.x + * [Couchbase Java SDK](https://docs.couchbase.com/java-sdk/current/hello-world/overview.html) 3.8.3 (Optional¹), See [leralik's Plugin Repository](https://github.com/leralik/skywalking-java-agent-couchbase-plugin) * Service Discovery * [Netflix Eureka](https://github.com/Netflix/eureka) * Distributed Coordination @@ -194,7 +195,7 @@ The meter plugin provides the advanced metrics collections, which are not a part ___ ¹Due to license incompatibilities/restrictions these plugins are hosted and released in 3rd part repository, - go to [SkyAPM java plugin extension repository](https://github.com/SkyAPM/java-plugin-extensions) to get these. + the address following the plugin can help you to get it. ²These plugins affect the performance or must be used under some conditions, from experiences. So only released in `/optional-plugins` or `/bootstrap-plugins`, copy to `/plugins` in order to make them work. diff --git a/docs/en/setup/service-agent/java-agent/configurations.md b/docs/en/setup/service-agent/java-agent/configurations.md index 9c6cc2d7f6..ddc14a145e 100644 --- a/docs/en/setup/service-agent/java-agent/configurations.md +++ b/docs/en/setup/service-agent/java-agent/configurations.md @@ -107,15 +107,15 @@ This is the properties list supported in `agent/config/agent.config`. | `plugin.lettuce.trace_redis_parameters` | If set to true, the parameters of Redis commands would be collected by Lettuce agent. | SW_PLUGIN_LETTUCE_TRACE_REDIS_PARAMETERS | `false` | | `plugin.lettuce.redis_parameter_max_length` | If set to positive number and `plugin.lettuce.trace_redis_parameters` is set to `true`, Redis command parameters would be collected and truncated to this length. | SW_PLUGIN_LETTUCE_REDIS_PARAMETER_MAX_LENGTH | `128` | | `plugin.lettuce.operation_mapping_write` | Specify which command should be converted to `write` operation | SW_PLUGIN_LETTUCE_OPERATION_MAPPING_WRITE | | -| `plugin.lettuce.operation_mapping_read ` | Specify which command should be converted to `read` operation | SW_PLUGIN_LETTUCE_OPERATION_MAPPING_READ | Referenc [Lettuce-5.x-plugin](https://github.com/apache/skywalking-java/blob/main/apm-sniffer/apm-sdk-plugin/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/LettucePluginConfig.java) | +| `plugin.lettuce.operation_mapping_read ` | Specify which command should be converted to `read` operation | SW_PLUGIN_LETTUCE_OPERATION_MAPPING_READ | Reference [Lettuce-5.x-plugin](https://github.com/apache/skywalking-java/blob/main/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/LettucePluginConfig.java) | | `plugin.jedis.trace_redis_parameters` | If set to true, the parameters of Redis commands would be collected by Jedis agent. | SW_PLUGIN_JEDIS_TRACE_REDIS_PARAMETERS | `false` | | `plugin.jedis.redis_parameter_max_length` | If set to positive number and `plugin.jedis.trace_redis_parameters` is set to `true`, Redis command parameters would be collected and truncated to this length. | SW_PLUGIN_JEDIS_REDIS_PARAMETER_MAX_LENGTH | `128` | | `plugin.jedis.operation_mapping_write` | Specify which command should be converted to `write` operation | SW_PLUGIN_JEDIS_OPERATION_MAPPING_WRITE | | -| `plugin.jedis.operation_mapping_read ` | Specify which command should be converted to `read` operation | SW_PLUGIN_JEDIS_OPERATION_MAPPING_READ | Referenc [Jedis-4.x-plugin](https://github.com/apache/skywalking-java/blob/main/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisPluginConfig.java) [jedis-2.x-3.x-plugin](https://github.com/apache/skywalking-java/blob/main/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v3/JedisPluginConfig.java) | +| `plugin.jedis.operation_mapping_read ` | Specify which command should be converted to `read` operation | SW_PLUGIN_JEDIS_OPERATION_MAPPING_READ | Reference [Jedis-4.x-plugin](https://github.com/apache/skywalking-java/blob/main/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisPluginConfig.java) [jedis-2.x-3.x-plugin](https://github.com/apache/skywalking-java/blob/main/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v3/JedisPluginConfig.java) | | `plugin.redisson.trace_redis_parameters` | If set to true, the parameters of Redis commands would be collected by Redisson agent. | SW_PLUGIN_REDISSON_TRACE_REDIS_PARAMETERS | `false` | | `plugin.redisson.redis_parameter_max_length` | If set to positive number and `plugin.redisson.trace_redis_parameters` is set to `true`, Redis command parameters would be collected and truncated to this length. | SW_PLUGIN_REDISSON_REDIS_PARAMETER_MAX_LENGTH | `128` | | `plugin.redisson.operation_mapping_write` | Specify which command should be converted to `write` operation | SW_PLUGIN_REDISSON_OPERATION_MAPPING_WRITE | | -| `plugin.redisson.operation_mapping_read ` | Specify which command should be converted to `read` operation | SW_PLUGIN_REDISSON_OPERATION_MAPPING_READ | Referenc [Redisson-3.x-plugin](https://github.com/apache/skywalking-java/blob/main/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java) | +| `plugin.redisson.operation_mapping_read ` | Specify which command should be converted to `read` operation | SW_PLUGIN_REDISSON_OPERATION_MAPPING_READ | Reference [Redisson-3.x-plugin](https://github.com/apache/skywalking-java/blob/main/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedissonPluginConfig.java) | | `plugin.neo4j.trace_cypher_parameters` | If set to true, the parameters of the cypher would be collected. | SW_PLUGIN_NEO4J_TRACE_CYPHER_PARAMETERS | `false` | | `plugin.neo4j.cypher_parameters_max_length` | If set to positive number, the `db.cypher.parameters` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem. | SW_PLUGIN_NEO4J_CYPHER_PARAMETERS_MAX_LENGTH | `512` | | `plugin.neo4j.cypher_body_max_length` | If set to positive number, the `db.statement` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem. | SW_PLUGIN_NEO4J_CYPHER_BODY_MAX_LENGTH | `2048` | From 4bb2c2ff89f1d3d0a2b6e78af5e5d4ce3d22b07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9B=9E=E6=9D=91=E7=9A=84=E8=AF=B1=E6=83=91?= <1214585092@qq.com> Date: Mon, 28 Jul 2025 20:31:25 +0800 Subject: [PATCH 068/114] Add support gRPC 1.59.x and 1.70.x server interceptor trace (#764) Root cause, grpc/grpc-java@050ae18 made changes to AbstractServerImplBuilder, which causes a functional issue with the gRPC tracing plugin. --- .github/workflows/plugins-test.0.yaml | 2 + CHANGES.md | 1 + ...tractServerImplBuilderInstrumentation.java | 8 +- .../AbstractServerImplBuilderInterceptor.java | 51 +- .../bin/startup.sh | 21 + .../config/expectedData.yaml | 458 ++++++++++++++++++ .../configuration.yml | 22 + .../grpc-1.30.x-1.39.x-scenario/pom.xml | 170 +++++++ .../src/main/assembly/assembly.xml | 41 ++ .../apm/testcase/grpc/Application.java | 34 ++ .../grpc/consumr/ConsumerInterceptor.java | 109 +++++ .../grpc/controller/CaseController.java | 137 ++++++ .../grpc/provider/ProviderConfiguration.java | 44 ++ .../interceptor/ProviderInterceptor.java | 96 ++++ .../GreeterBlockingErrorServiceImpl.java | 31 ++ .../service/GreeterBlockingServiceImpl.java | 32 ++ .../provider/service/GreeterServiceImpl.java | 52 ++ .../src/main/proto/GreetService.proto | 43 ++ .../src/main/resources/application.yaml | 23 + .../src/main/resources/log4j2.xml | 30 ++ .../support-version.list | 31 ++ .../bin/startup.sh | 21 + .../config/expectedData.yaml | 458 ++++++++++++++++++ .../configuration.yml | 22 + .../grpc-1.59.x-1.70.x-scenario/pom.xml | 163 +++++++ .../src/main/assembly/assembly.xml | 41 ++ .../apm/testcase/grpc/Application.java | 34 ++ .../grpc/consumr/ConsumerInterceptor.java | 109 +++++ .../grpc/controller/CaseController.java | 137 ++++++ .../grpc/provider/ProviderConfiguration.java | 44 ++ .../interceptor/ProviderInterceptor.java | 96 ++++ .../GreeterBlockingErrorServiceImpl.java | 31 ++ .../service/GreeterBlockingServiceImpl.java | 32 ++ .../provider/service/GreeterServiceImpl.java | 52 ++ .../src/main/proto/GreetService.proto | 43 ++ .../src/main/resources/application.yaml | 23 + .../src/main/resources/log4j2.xml | 30 ++ .../support-version.list | 35 ++ 38 files changed, 2800 insertions(+), 7 deletions(-) create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/Application.java create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/consumr/ConsumerInterceptor.java create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/interceptor/ProviderInterceptor.java create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingServiceImpl.java create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/proto/GreetService.proto create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/support-version.list create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/Application.java create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/consumr/ConsumerInterceptor.java create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/interceptor/ProviderInterceptor.java create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingServiceImpl.java create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/proto/GreetService.proto create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/support-version.list diff --git a/.github/workflows/plugins-test.0.yaml b/.github/workflows/plugins-test.0.yaml index 19127048b5..a3f2653a1e 100644 --- a/.github/workflows/plugins-test.0.yaml +++ b/.github/workflows/plugins-test.0.yaml @@ -80,6 +80,8 @@ jobs: - gateway-2.1.x-scenario - gateway-2.0.x-scenario - grpc-scenario + - grpc-1.59.x-1.70.x-scenario + - grpc-1.30.x-1.39.x-scenario - gson-scenario - guava-cache-scenario - elasticjob-3.x-scenario diff --git a/CHANGES.md b/CHANGES.md index 57df5dde95..4f1bc7cee8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ Release Notes. * Fix RabbitMQ Consumer could not receive handleCancelOk callback. * Support for tracking in lettuce versions 6.5.x and above. * Upgrade byte-buddy version to 1.17.6. +* Support gRPC 1.59.x and 1.70.x server interceptor trace All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractServerImplBuilderInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractServerImplBuilderInstrumentation.java index f32987f4bc..bd71445d7c 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractServerImplBuilderInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractServerImplBuilderInstrumentation.java @@ -24,14 +24,13 @@ 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.MultiClassNameMatch; 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 AbstractServerImplBuilderInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { - public static final String ENHANCE_CLASS = "io.grpc.internal.AbstractServerImplBuilder"; public static final String ENHANCE_METHOD = "build"; public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.server.AbstractServerImplBuilderInterceptor"; @@ -64,6 +63,9 @@ public boolean isOverrideArgs() { @Override protected ClassMatch enhanceClass() { - return byName(ENHANCE_CLASS); + return MultiClassNameMatch.byMultiClassMatch( + "io.grpc.internal.AbstractServerImplBuilder", //grpc version <= 1.58.1 + "io.grpc.internal.ServerImplBuilder" //grpc version >= 1.59.0 + ); } } diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/AbstractServerImplBuilderInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/AbstractServerImplBuilderInterceptor.java index c02cf566de..cf1bcf4f76 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/AbstractServerImplBuilderInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/AbstractServerImplBuilderInterceptor.java @@ -20,7 +20,11 @@ import io.grpc.ServerBuilder; +import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; @@ -30,14 +34,26 @@ * {@link AbstractServerImplBuilderInterceptor} add the {@link ServerInterceptor} interceptor for every ServerService. */ public class AbstractServerImplBuilderInterceptor implements InstanceMethodsAroundInterceptor { + private final static Map, Field> FIELD_CACHE = new HashMap<>(); + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) { + MethodInterceptResult result) throws Throwable { if (objInst.getSkyWalkingDynamicField() == null) { ServerBuilder builder = (ServerBuilder) objInst; - ServerInterceptor interceptor = new ServerInterceptor(); - builder.intercept(interceptor); - objInst.setSkyWalkingDynamicField(interceptor); + Field field = findField(builder.getClass()); + if (field != null) { + List interceptors = (List) field.get(builder); + boolean hasCustomInterceptor = interceptors.stream() + .anyMatch(i -> i.getClass() == ServerInterceptor.class); + + if (!hasCustomInterceptor) { + ServerInterceptor interceptor = new ServerInterceptor(); + builder.intercept(interceptor); + objInst.setSkyWalkingDynamicField(interceptor); + } + + } } } @@ -52,4 +68,31 @@ public void handleMethodException(EnhancedInstance objInst, Method method, Objec Class[] argumentsTypes, Throwable t) { } + + private static Field findField(Class clazz) { + if (FIELD_CACHE.containsKey(clazz)) { + return FIELD_CACHE.get(clazz); + } + synchronized (AbstractServerImplBuilderInterceptor.class) { + if (FIELD_CACHE.containsKey(clazz)) { + return FIELD_CACHE.get(clazz); + } + Field field = doFindField(clazz); + FIELD_CACHE.put(clazz, field); + return field; + } + } + + private static Field doFindField(Class clazz) { + while (clazz != null) { + for (Field f : clazz.getDeclaredFields()) { + if (f.getName().equals("interceptors")) { + f.setAccessible(true); + return f; + } + } + clazz = clazz.getSuperclass(); + } + return null; + } } diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/bin/startup.sh b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..aeac2a7b77 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-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/grpc-1.30.x-1.39.x-scenario.jar & diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..b4551acf3e --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/config/expectedData.yaml @@ -0,0 +1,458 @@ +# 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: grpc-1.30.x-1.39.x-scenario + segmentSize: gt 10 + segments: + - segmentId: not null + spans: + - operationName: GreeterBlocking.sayHello + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Entry + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario, networkAddress: '127.0.0.1:18080', + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Request/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Request/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Request/onComplete + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Entry + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario, networkAddress: '127.0.0.1:18080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/server/Response/onMessage + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: Greeter.sayHello/server/Request/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: Greeter.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Response/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GreeterBlocking.sayHello/server/Response/onClose + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + tags: + - {key: rpc.status_code, value: OK} + skipAnalysis: 'false' + - operationName: GreeterBlocking.sayHello/server/Request/onHalfClose + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GreeterBlocking.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/server/Response/onMessage + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: Greeter.sayHello/server/Request/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: Greeter.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/server/Response/onClose + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + tags: + - {key: rpc.status_code, value: OK} + skipAnalysis: 'false' + - operationName: Greeter.sayHello/server/Request/onHalfClose + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: Greeter.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Response/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Response/onClose + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GreeterBlockingError.sayHello + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Entry + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario, networkAddress: '127.0.0.1:18080', + refType: CrossProcess, parentSpanId: 5, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GreeterBlockingError.sayHello/server/Response/onClose + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: true + spanType: Local + peer: '' + tags: + - {key: rpc.status_code, value: UNKNOWN} + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: java.lang.Exception} + - {key: message, value: ''} + - {key: stack, value: not null} + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello/server/Request/onHalfClose + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GreeterBlockingError.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.30.x-1.39.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Exit + peer: '127.0.0.1:18080' + skipAnalysis: 'false' + - operationName: GreeterBlocking.sayHello/client/Request/onComplete + parentSpanId: 2 + spanId: 3 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: GreeterBlocking.sayHello/client/Response/onClose + parentSpanId: 2 + spanId: 4 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: GreeterBlocking.sayHello + parentSpanId: 0 + panId: 2 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Exit + peer: '127.0.0.1:18080' + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello/client/Request/onComplete + parentSpanId: 5 + spanId: 6 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello/client/Response/onClose + parentSpanId: 5 + spanId: 7 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: true + spanType: Local + peer: '' + tags: + - {key: rpc.status_code, value: UNKNOWN} + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: io.grpc.StatusRuntimeException} + - {key: message, value: UNKNOWN} + - {key: stack, value: not null} + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello/client/Request/onCancel + parentSpanId: 5 + spanId: 8 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: true + spanType: Local + peer: '' + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: io.grpc.StatusRuntimeException} + - {key: message, value: UNKNOWN} + - {key: stack, value: not null} + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello + parentSpanId: 0 + spanId: 5 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: true + spanType: Exit + peer: 127.0.0.1:18080 + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: io.grpc.StatusRuntimeException} + - {key: message, value: UNKNOWN} + - {key: stack, value: not null} + skipAnalysis: 'false' + - operationName: GET:/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: true + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '500'} + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: org.springframework.web.util.NestedServletException} + - {key: message, value: 'Request processing failed; nested exception is io.grpc.StatusRuntimeException: + UNKNOWN'} + - {key: stack, value: not null} + - logEvent: + - {key: forward-url, value: /grpc-1.30.x-1.39.x-scenario/error} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/configuration.yml b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/configuration.yml new file mode 100644 index 0000000000..932097e647 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-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/grpc-1.30.x-1.39.x-scenario/case/grpc-1.30.x-1.39.x-scenario +healthCheck: http://localhost:8080/grpc-1.30.x-1.39.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: +dependencies: diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/pom.xml b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/pom.xml new file mode 100644 index 0000000000..de23b46190 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/pom.xml @@ -0,0 +1,170 @@ + + + + + org.apache.skywalking.apm.testcase + grpc-1.30.x-1.39.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + 1.6.2 + + 1.39.0 + + 2.1.6.RELEASE + + + skywalking-grpc-1.30.x-1.39.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + + io.grpc + grpc-all + ${test.framework.version} + + + io.grpc + grpc-rls + + + + + + + + + grpc-1.30.x-1.39.x-scenario + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + + initialize + + detect + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.6.1 + + + com.google.protobuf:protoc:3.11.4:exe:${os.detected.classifier} + + grpc-java + io.grpc:protoc-gen-grpc-java:${test.framework.version}:exe:${os.detected.classifier} + + + + + + compile + compile-custom + + + + + + + diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..9ba3b28c36 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/grpc-1.30.x-1.39.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/Application.java b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/Application.java new file mode 100644 index 0000000000..052e0f7e3b --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/Application.java @@ -0,0 +1,34 @@ +/* + * 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.testcase.grpc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } +} diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/consumr/ConsumerInterceptor.java b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/consumr/ConsumerInterceptor.java new file mode 100644 index 0000000000..e8a35d0359 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/consumr/ConsumerInterceptor.java @@ -0,0 +1,109 @@ +/* + * 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.testcase.grpc.consumr; + +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall; +import io.grpc.ForwardingClientCallListener; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.grpc.Status; +import javax.annotation.Nullable; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ConsumerInterceptor implements ClientInterceptor { + + private static final Logger LOGGER = LogManager.getLogger(ConsumerInterceptor.class); + + @Override + public ClientCall interceptCall(MethodDescriptor descriptor, + CallOptions options, Channel channel) { + LOGGER.info("start interceptor!"); + LOGGER.info("method type: {}", descriptor.getType()); + return new ForwardingClientCall.SimpleForwardingClientCall(channel.newCall(descriptor, options)) { + @Override + public void start(Listener responseListener, Metadata headers) { + LOGGER.info("Peer: {}", channel.authority()); + LOGGER.info("Operation Name : {}", descriptor.getFullMethodName()); + Interceptor tracingResponseListener = new Interceptor(responseListener); + tracingResponseListener.contextSnapshot = "contextSnapshot"; + delegate().start(tracingResponseListener, headers); + } + + @Override + public void cancel(@Nullable String message, @Nullable Throwable cause) { + LOGGER.info("cancel"); + super.cancel(message, cause); + } + + @Override + public void halfClose() { + LOGGER.info("halfClose"); + super.halfClose(); + } + + @Override + public void sendMessage(REQ_T message) { + LOGGER.info("sendMessage ...."); + super.sendMessage(message); + } + }; + } + + private static class Interceptor extends ForwardingClientCallListener.SimpleForwardingClientCallListener { + private static final Logger LOGGER = LogManager.getLogger(Interceptor.class); + + private Object contextSnapshot; + + protected Interceptor(ClientCall.Listener delegate) { + super(delegate); + } + + @Override + public void onHeaders(Metadata headers) { + LOGGER.info("on Headers"); + for (String key : headers.keys()) { + LOGGER.info("Receive key: {}", key); + } + delegate().onHeaders(headers); + } + + @Override + public void onMessage(RESP_T message) { + LOGGER.info("contextSnapshot: {}", contextSnapshot); + delegate().onMessage(message); + } + + @Override + public void onClose(Status status, Metadata trailers) { + LOGGER.info("on close"); + delegate().onClose(status, trailers); + } + + @Override + public void onReady() { + LOGGER.info("on Ready"); + super.onReady(); + } + } +} diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java new file mode 100644 index 0000000000..c97804e90b --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java @@ -0,0 +1,137 @@ +/* + * 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.testcase.grpc.controller; + +import io.grpc.ClientInterceptors; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.stub.ClientCallStreamObserver; +import io.grpc.stub.ClientResponseObserver; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import javax.annotation.PostConstruct; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.grpc.consumr.ConsumerInterceptor; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingErrorGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +public class CaseController { + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + private static final String SUCCESS = "Success"; + + private final String grpcProviderHost = "127.0.0.1"; + private final int grpcProviderPort = 18080; + private ManagedChannel channel; + private GreeterGrpc.GreeterStub greeterStub; + private GreeterBlockingGrpc.GreeterBlockingBlockingStub greeterBlockingStub; + private GreeterBlockingErrorGrpc.GreeterBlockingErrorBlockingStub greeterBlockingErrorStub; + + @PostConstruct + public void up() { + channel = ManagedChannelBuilder.forAddress(grpcProviderHost, grpcProviderPort).usePlaintext().build(); + greeterStub = GreeterGrpc.newStub(ClientInterceptors.intercept(channel, new ConsumerInterceptor())); + greeterBlockingStub = GreeterBlockingGrpc.newBlockingStub(ClientInterceptors.intercept(channel, new ConsumerInterceptor())); + greeterBlockingErrorStub = GreeterBlockingErrorGrpc.newBlockingStub(ClientInterceptors.intercept(channel, new ConsumerInterceptor())); + } + + @RequestMapping("/grpc-1.30.x-1.39.x-scenario") + @ResponseBody + public String testcase() { + greetService(); + greetBlockingService(); + greetBlockingErrorService(); + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + // your codes + return SUCCESS; + } + + private static List names() { + return Arrays.asList("Sophia", "Jackson"); + } + + private void greetService() { + ClientResponseObserver helloReplyStreamObserver = new ClientResponseObserver() { + private ClientCallStreamObserver requestStream; + + @Override + public void beforeStart(ClientCallStreamObserver observer) { + this.requestStream = observer; + this.requestStream.setOnReadyHandler(new Runnable() { + Iterator iterator = names().iterator(); + + @Override + public void run() { + while (requestStream.isReady()) { + if (iterator.hasNext()) { + String name = iterator.next(); + HelloRequest request = HelloRequest.newBuilder().setName(name).build(); + requestStream.onNext(request); + } else { + requestStream.onCompleted(); + } + } + } + }); + } + + @Override + public void onNext(HelloReply reply) { + LOGGER.info("Receive an message from provider. message: {}", reply.getMessage()); + requestStream.request(1); + } + + public void onError(Throwable throwable) { + LOGGER.error("Failed to send data", throwable); + } + + public void onCompleted() { + LOGGER.info("All Done"); + } + }; + + greeterStub.sayHello(helloReplyStreamObserver); + } + + private void greetBlockingService() { + HelloRequest request = HelloRequest.newBuilder().setName("Sophia").build(); + greeterBlockingStub.sayHello(request); + } + + private void greetBlockingErrorService() { + HelloRequest request = HelloRequest.newBuilder().setName("Tony").build(); + greeterBlockingErrorStub.sayHello(request); + } +} diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java new file mode 100644 index 0000000000..8541c403b1 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java @@ -0,0 +1,44 @@ +/* + * 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.testcase.grpc.provider; + +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.ServerInterceptors; +import org.apache.skywalking.apm.testcase.grpc.provider.interceptor.ProviderInterceptor; +import org.apache.skywalking.apm.testcase.grpc.provider.service.GreeterBlockingErrorServiceImpl; +import org.apache.skywalking.apm.testcase.grpc.provider.service.GreeterBlockingServiceImpl; +import org.apache.skywalking.apm.testcase.grpc.provider.service.GreeterServiceImpl; +import org.springframework.beans.factory.annotation.Configurable; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +@Configurable +@Component +public class ProviderConfiguration { + + @Bean(initMethod = "start", destroyMethod = "shutdown") + public Server server() { + return ServerBuilder.forPort(18080) + .addService(ServerInterceptors.intercept(new GreeterServiceImpl(), new ProviderInterceptor())) + .addService(ServerInterceptors.intercept(new GreeterBlockingServiceImpl(), new ProviderInterceptor())) + .addService(ServerInterceptors.intercept(new GreeterBlockingErrorServiceImpl(), new ProviderInterceptor())) + .build(); + } +} diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/interceptor/ProviderInterceptor.java b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/interceptor/ProviderInterceptor.java new file mode 100644 index 0000000000..26647b41a8 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/interceptor/ProviderInterceptor.java @@ -0,0 +1,96 @@ +/* + * 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.testcase.grpc.provider.interceptor; + +import io.grpc.ForwardingServerCall; +import io.grpc.ForwardingServerCallListener; +import io.grpc.Metadata; +import io.grpc.ServerCall; +import io.grpc.ServerCallHandler; +import io.grpc.ServerInterceptor; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ProviderInterceptor implements ServerInterceptor { + private static final Logger LOGGER = LogManager.getLogger(ProviderInterceptor.class); + + @Override + public ServerCall.Listener interceptCall(ServerCall call, Metadata metadata, + ServerCallHandler handler) { + Map headerMap = new HashMap(); + for (String key : metadata.keys()) { + LOGGER.info("Receive key: {}", key); + if (!key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) { + String value = metadata.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER)); + + headerMap.put(key, value); + } + } + LOGGER.info("authority : {}", call.getAuthority()); + return new ForwardingServerCallListener.SimpleForwardingServerCallListener(handler.startCall(new ForwardingServerCall.SimpleForwardingServerCall(call) { + @Override + public void sendHeaders(Metadata responseHeaders) { + LOGGER.info("sendHeaders...."); + Metadata.Key headerKey = Metadata.Key.of("test-server", Metadata.ASCII_STRING_MARSHALLER); + responseHeaders.put(headerKey, "test-server"); + delegate().sendHeaders(responseHeaders); + } + + @Override + public void sendMessage(RESQ_T message) { + delegate().sendMessage(message); + } + + }, metadata)) { + @Override + public void onReady() { + LOGGER.info("onReady...."); + delegate().onReady(); + } + + @Override + public void onCancel() { + LOGGER.info("onCancel...."); + delegate().onCancel(); + } + + @Override + public void onComplete() { + LOGGER.info("onComplete...."); + delegate().onComplete(); + } + + @Override + public void onHalfClose() { + LOGGER.info("onHalfClose...."); + delegate().onHalfClose(); + } + + @Override + public void onMessage(REQ_T message) { + LOGGER.info("onMessage...."); + delegate().onMessage(message); + } + }; + } +} diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java new file mode 100644 index 0000000000..3cd6394a48 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java @@ -0,0 +1,31 @@ +/* + * 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.testcase.grpc.provider.service; + +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingErrorGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; + +public class GreeterBlockingErrorServiceImpl extends GreeterBlockingErrorGrpc.GreeterBlockingErrorImplBase { + @Override + public void sayHello(HelloRequest request, StreamObserver responseObserver) { + responseObserver.onError(new Exception()); + } +} diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingServiceImpl.java b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingServiceImpl.java new file mode 100644 index 0000000000..2f156bc62f --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingServiceImpl.java @@ -0,0 +1,32 @@ +/* + * 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.testcase.grpc.provider.service; + +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; + +public class GreeterBlockingServiceImpl extends GreeterBlockingGrpc.GreeterBlockingImplBase { + @Override + public void sayHello(HelloRequest request, StreamObserver responseObserver) { + responseObserver.onNext(HelloReply.newBuilder().setMessage("Hi," + request.getName()).build()); + responseObserver.onCompleted(); + } +} diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java new file mode 100644 index 0000000000..5235d09318 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.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.testcase.grpc.provider.service; + +import io.grpc.stub.StreamObserver; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; + +public class GreeterServiceImpl extends GreeterGrpc.GreeterImplBase { + + private static final Logger LOGGER = LogManager.getLogger(GreeterServiceImpl.class); + + @Override + public StreamObserver sayHello(final StreamObserver responseObserver) { + StreamObserver requestStreamObserver = new StreamObserver() { + + public void onNext(HelloRequest request) { + LOGGER.info("Receive an message from client. Message: {}", request.getName()); + responseObserver.onNext(HelloReply.newBuilder().setMessage("Hi," + request.getName()).build()); + } + + public void onError(Throwable throwable) { + responseObserver.onError(throwable); + } + + public void onCompleted() { + LOGGER.info("End the stream."); + responseObserver.onCompleted(); + } + }; + return requestStreamObserver; + } +} diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/proto/GreetService.proto b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/proto/GreetService.proto new file mode 100644 index 0000000000..fd5ba4a8f1 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/proto/GreetService.proto @@ -0,0 +1,43 @@ +/* + * 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. + * + */ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "org.apache.skywalking.apm.testcase.grpc.proto"; + +service Greeter { + rpc SayHello (stream HelloRequest) returns (stream HelloReply) { + } +} + +service GreeterBlocking { + rpc SayHello (HelloRequest) returns (HelloReply) { + } +} +service GreeterBlockingError { + rpc SayHello (HelloRequest) returns (HelloReply) { + } +} + +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; +} \ No newline at end of file diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..5f9c909a1b --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +# +# 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 + servlet: + context-path: /grpc-1.30.x-1.39.x-scenario +logging: + config: classpath:log4j2.xml diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/support-version.list b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/support-version.list new file mode 100644 index 0000000000..5c01dfaf60 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.30.x-1.39.x-scenario/support-version.list @@ -0,0 +1,31 @@ +# 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. + +# INTERNAL: HTTP/2 error code: INTERNAL_ERROR Received Goaway occur in test cases 1.0.0 to 1.5.0 +# So these versions were not included in support-version.list. if you know what caused it, please help us. + +# Contains only the last version number of each minor version + +1.39.0 +1.38.0 +1.37.0 +1.36.0 +1.35.0 +1.34.0 +1.33.0 +1.32.1 +1.31.0 +1.30.0 diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/bin/startup.sh b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..54d5003fe6 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-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/grpc-1.59.x-1.70.x-scenario.jar & diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..2cbf91a2ea --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/config/expectedData.yaml @@ -0,0 +1,458 @@ +# 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: grpc-1.59.x-1.70.x-scenario + segmentSize: gt 10 + segments: + - segmentId: not null + spans: + - operationName: GreeterBlocking.sayHello + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Entry + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario, networkAddress: '127.0.0.1:18080', + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Request/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Request/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Request/onComplete + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Entry + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario, networkAddress: '127.0.0.1:18080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/server/Response/onMessage + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: Greeter.sayHello/server/Request/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: Greeter.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Response/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GreeterBlocking.sayHello/server/Response/onClose + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + tags: + - {key: rpc.status_code, value: OK} + skipAnalysis: 'false' + - operationName: GreeterBlocking.sayHello/server/Request/onHalfClose + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GreeterBlocking.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/server/Response/onMessage + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: Greeter.sayHello/server/Request/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: Greeter.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/server/Response/onClose + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + tags: + - {key: rpc.status_code, value: OK} + skipAnalysis: 'false' + - operationName: Greeter.sayHello/server/Request/onHalfClose + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: Greeter.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Response/onMessage + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Response/onClose + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario, networkAddress: '', refType: CrossThread, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GreeterBlockingError.sayHello + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Entry + peer: '' + refs: + - {parentEndpoint: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario, networkAddress: '127.0.0.1:18080', + refType: CrossProcess, parentSpanId: 5, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GreeterBlockingError.sayHello/server/Response/onClose + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: true + spanType: Local + peer: '' + tags: + - {key: rpc.status_code, value: UNKNOWN} + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: java.lang.Exception} + - {key: message, value: ''} + - {key: stack, value: not null} + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello/server/Request/onHalfClose + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GreeterBlockingError.sayHello, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: grpc-1.59.x-1.70.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: Greeter.sayHello + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Exit + peer: '127.0.0.1:18080' + skipAnalysis: 'false' + - operationName: GreeterBlocking.sayHello/client/Request/onComplete + parentSpanId: 2 + spanId: 3 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: GreeterBlocking.sayHello/client/Response/onClose + parentSpanId: 2 + spanId: 4 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: GreeterBlocking.sayHello + parentSpanId: 0 + panId: 2 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Exit + peer: '127.0.0.1:18080' + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello/client/Request/onComplete + parentSpanId: 5 + spanId: 6 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello/client/Response/onClose + parentSpanId: 5 + spanId: 7 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: true + spanType: Local + peer: '' + tags: + - {key: rpc.status_code, value: UNKNOWN} + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: io.grpc.StatusRuntimeException} + - {key: message, value: UNKNOWN} + - {key: stack, value: not null} + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello/client/Request/onCancel + parentSpanId: 5 + spanId: 8 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: true + spanType: Local + peer: '' + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: io.grpc.StatusRuntimeException} + - {key: message, value: UNKNOWN} + - {key: stack, value: not null} + skipAnalysis: 'false' + - operationName: GreeterBlockingError.sayHello + parentSpanId: 0 + spanId: 5 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + isError: true + spanType: Exit + peer: 127.0.0.1:18080 + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: io.grpc.StatusRuntimeException} + - {key: message, value: UNKNOWN} + - {key: stack, value: not null} + skipAnalysis: 'false' + - operationName: GET:/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: true + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '500'} + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: org.springframework.web.util.NestedServletException} + - {key: message, value: 'Request processing failed; nested exception is io.grpc.StatusRuntimeException: + UNKNOWN'} + - {key: stack, value: not null} + - logEvent: + - {key: forward-url, value: /grpc-1.59.x-1.70.x-scenario/error} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/configuration.yml b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/configuration.yml new file mode 100644 index 0000000000..858c323d01 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-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/grpc-1.59.x-1.70.x-scenario/case/grpc-1.59.x-1.70.x-scenario +healthCheck: http://localhost:8080/grpc-1.59.x-1.70.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: +dependencies: diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/pom.xml b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/pom.xml new file mode 100644 index 0000000000..0794a1cb21 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/pom.xml @@ -0,0 +1,163 @@ + + + + + org.apache.skywalking.apm.testcase + grpc-1.59.x-1.70.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + 1.6.2 + + 1.59.0 + + 2.1.6.RELEASE + + + skywalking-grpc-1.59.x-1.70.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + + io.grpc + grpc-all + ${test.framework.version} + + + + + + grpc-1.59.x-1.70.x-scenario + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + + initialize + + detect + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.6.1 + + + com.google.protobuf:protoc:3.23.4:exe:${os.detected.classifier} + + grpc-java + io.grpc:protoc-gen-grpc-java:${test.framework.version}:exe:${os.detected.classifier} + + + + + + compile + compile-custom + + + + + + + diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..11d5b1f62c --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/grpc-1.59.x-1.70.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/Application.java b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/Application.java new file mode 100644 index 0000000000..052e0f7e3b --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/Application.java @@ -0,0 +1,34 @@ +/* + * 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.testcase.grpc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } +} diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/consumr/ConsumerInterceptor.java b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/consumr/ConsumerInterceptor.java new file mode 100644 index 0000000000..e8a35d0359 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/consumr/ConsumerInterceptor.java @@ -0,0 +1,109 @@ +/* + * 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.testcase.grpc.consumr; + +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall; +import io.grpc.ForwardingClientCallListener; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.grpc.Status; +import javax.annotation.Nullable; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ConsumerInterceptor implements ClientInterceptor { + + private static final Logger LOGGER = LogManager.getLogger(ConsumerInterceptor.class); + + @Override + public ClientCall interceptCall(MethodDescriptor descriptor, + CallOptions options, Channel channel) { + LOGGER.info("start interceptor!"); + LOGGER.info("method type: {}", descriptor.getType()); + return new ForwardingClientCall.SimpleForwardingClientCall(channel.newCall(descriptor, options)) { + @Override + public void start(Listener responseListener, Metadata headers) { + LOGGER.info("Peer: {}", channel.authority()); + LOGGER.info("Operation Name : {}", descriptor.getFullMethodName()); + Interceptor tracingResponseListener = new Interceptor(responseListener); + tracingResponseListener.contextSnapshot = "contextSnapshot"; + delegate().start(tracingResponseListener, headers); + } + + @Override + public void cancel(@Nullable String message, @Nullable Throwable cause) { + LOGGER.info("cancel"); + super.cancel(message, cause); + } + + @Override + public void halfClose() { + LOGGER.info("halfClose"); + super.halfClose(); + } + + @Override + public void sendMessage(REQ_T message) { + LOGGER.info("sendMessage ...."); + super.sendMessage(message); + } + }; + } + + private static class Interceptor extends ForwardingClientCallListener.SimpleForwardingClientCallListener { + private static final Logger LOGGER = LogManager.getLogger(Interceptor.class); + + private Object contextSnapshot; + + protected Interceptor(ClientCall.Listener delegate) { + super(delegate); + } + + @Override + public void onHeaders(Metadata headers) { + LOGGER.info("on Headers"); + for (String key : headers.keys()) { + LOGGER.info("Receive key: {}", key); + } + delegate().onHeaders(headers); + } + + @Override + public void onMessage(RESP_T message) { + LOGGER.info("contextSnapshot: {}", contextSnapshot); + delegate().onMessage(message); + } + + @Override + public void onClose(Status status, Metadata trailers) { + LOGGER.info("on close"); + delegate().onClose(status, trailers); + } + + @Override + public void onReady() { + LOGGER.info("on Ready"); + super.onReady(); + } + } +} diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java new file mode 100644 index 0000000000..2a26b99e96 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java @@ -0,0 +1,137 @@ +/* + * 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.testcase.grpc.controller; + +import io.grpc.ClientInterceptors; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.stub.ClientCallStreamObserver; +import io.grpc.stub.ClientResponseObserver; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import javax.annotation.PostConstruct; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.grpc.consumr.ConsumerInterceptor; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingErrorGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +public class CaseController { + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + private static final String SUCCESS = "Success"; + + private final String grpcProviderHost = "127.0.0.1"; + private final int grpcProviderPort = 18080; + private ManagedChannel channel; + private GreeterGrpc.GreeterStub greeterStub; + private GreeterBlockingGrpc.GreeterBlockingBlockingStub greeterBlockingStub; + private GreeterBlockingErrorGrpc.GreeterBlockingErrorBlockingStub greeterBlockingErrorStub; + + @PostConstruct + public void up() { + channel = ManagedChannelBuilder.forAddress(grpcProviderHost, grpcProviderPort).usePlaintext().build(); + greeterStub = GreeterGrpc.newStub(ClientInterceptors.intercept(channel, new ConsumerInterceptor())); + greeterBlockingStub = GreeterBlockingGrpc.newBlockingStub(ClientInterceptors.intercept(channel, new ConsumerInterceptor())); + greeterBlockingErrorStub = GreeterBlockingErrorGrpc.newBlockingStub(ClientInterceptors.intercept(channel, new ConsumerInterceptor())); + } + + @RequestMapping("/grpc-1.59.x-1.70.x-scenario") + @ResponseBody + public String testcase() { + greetService(); + greetBlockingService(); + greetBlockingErrorService(); + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + // your codes + return SUCCESS; + } + + private static List names() { + return Arrays.asList("Sophia", "Jackson"); + } + + private void greetService() { + ClientResponseObserver helloReplyStreamObserver = new ClientResponseObserver() { + private ClientCallStreamObserver requestStream; + + @Override + public void beforeStart(ClientCallStreamObserver observer) { + this.requestStream = observer; + this.requestStream.setOnReadyHandler(new Runnable() { + Iterator iterator = names().iterator(); + + @Override + public void run() { + while (requestStream.isReady()) { + if (iterator.hasNext()) { + String name = iterator.next(); + HelloRequest request = HelloRequest.newBuilder().setName(name).build(); + requestStream.onNext(request); + } else { + requestStream.onCompleted(); + } + } + } + }); + } + + @Override + public void onNext(HelloReply reply) { + LOGGER.info("Receive an message from provider. message: {}", reply.getMessage()); + requestStream.request(1); + } + + public void onError(Throwable throwable) { + LOGGER.error("Failed to send data", throwable); + } + + public void onCompleted() { + LOGGER.info("All Done"); + } + }; + + greeterStub.sayHello(helloReplyStreamObserver); + } + + private void greetBlockingService() { + HelloRequest request = HelloRequest.newBuilder().setName("Sophia").build(); + greeterBlockingStub.sayHello(request); + } + + private void greetBlockingErrorService() { + HelloRequest request = HelloRequest.newBuilder().setName("Tony").build(); + greeterBlockingErrorStub.sayHello(request); + } +} diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java new file mode 100644 index 0000000000..8541c403b1 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java @@ -0,0 +1,44 @@ +/* + * 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.testcase.grpc.provider; + +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.ServerInterceptors; +import org.apache.skywalking.apm.testcase.grpc.provider.interceptor.ProviderInterceptor; +import org.apache.skywalking.apm.testcase.grpc.provider.service.GreeterBlockingErrorServiceImpl; +import org.apache.skywalking.apm.testcase.grpc.provider.service.GreeterBlockingServiceImpl; +import org.apache.skywalking.apm.testcase.grpc.provider.service.GreeterServiceImpl; +import org.springframework.beans.factory.annotation.Configurable; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +@Configurable +@Component +public class ProviderConfiguration { + + @Bean(initMethod = "start", destroyMethod = "shutdown") + public Server server() { + return ServerBuilder.forPort(18080) + .addService(ServerInterceptors.intercept(new GreeterServiceImpl(), new ProviderInterceptor())) + .addService(ServerInterceptors.intercept(new GreeterBlockingServiceImpl(), new ProviderInterceptor())) + .addService(ServerInterceptors.intercept(new GreeterBlockingErrorServiceImpl(), new ProviderInterceptor())) + .build(); + } +} diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/interceptor/ProviderInterceptor.java b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/interceptor/ProviderInterceptor.java new file mode 100644 index 0000000000..26647b41a8 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/interceptor/ProviderInterceptor.java @@ -0,0 +1,96 @@ +/* + * 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.testcase.grpc.provider.interceptor; + +import io.grpc.ForwardingServerCall; +import io.grpc.ForwardingServerCallListener; +import io.grpc.Metadata; +import io.grpc.ServerCall; +import io.grpc.ServerCallHandler; +import io.grpc.ServerInterceptor; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class ProviderInterceptor implements ServerInterceptor { + private static final Logger LOGGER = LogManager.getLogger(ProviderInterceptor.class); + + @Override + public ServerCall.Listener interceptCall(ServerCall call, Metadata metadata, + ServerCallHandler handler) { + Map headerMap = new HashMap(); + for (String key : metadata.keys()) { + LOGGER.info("Receive key: {}", key); + if (!key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) { + String value = metadata.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER)); + + headerMap.put(key, value); + } + } + LOGGER.info("authority : {}", call.getAuthority()); + return new ForwardingServerCallListener.SimpleForwardingServerCallListener(handler.startCall(new ForwardingServerCall.SimpleForwardingServerCall(call) { + @Override + public void sendHeaders(Metadata responseHeaders) { + LOGGER.info("sendHeaders...."); + Metadata.Key headerKey = Metadata.Key.of("test-server", Metadata.ASCII_STRING_MARSHALLER); + responseHeaders.put(headerKey, "test-server"); + delegate().sendHeaders(responseHeaders); + } + + @Override + public void sendMessage(RESQ_T message) { + delegate().sendMessage(message); + } + + }, metadata)) { + @Override + public void onReady() { + LOGGER.info("onReady...."); + delegate().onReady(); + } + + @Override + public void onCancel() { + LOGGER.info("onCancel...."); + delegate().onCancel(); + } + + @Override + public void onComplete() { + LOGGER.info("onComplete...."); + delegate().onComplete(); + } + + @Override + public void onHalfClose() { + LOGGER.info("onHalfClose...."); + delegate().onHalfClose(); + } + + @Override + public void onMessage(REQ_T message) { + LOGGER.info("onMessage...."); + delegate().onMessage(message); + } + }; + } +} diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java new file mode 100644 index 0000000000..3cd6394a48 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java @@ -0,0 +1,31 @@ +/* + * 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.testcase.grpc.provider.service; + +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingErrorGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; + +public class GreeterBlockingErrorServiceImpl extends GreeterBlockingErrorGrpc.GreeterBlockingErrorImplBase { + @Override + public void sayHello(HelloRequest request, StreamObserver responseObserver) { + responseObserver.onError(new Exception()); + } +} diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingServiceImpl.java b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingServiceImpl.java new file mode 100644 index 0000000000..2f156bc62f --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingServiceImpl.java @@ -0,0 +1,32 @@ +/* + * 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.testcase.grpc.provider.service; + +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; + +public class GreeterBlockingServiceImpl extends GreeterBlockingGrpc.GreeterBlockingImplBase { + @Override + public void sayHello(HelloRequest request, StreamObserver responseObserver) { + responseObserver.onNext(HelloReply.newBuilder().setMessage("Hi," + request.getName()).build()); + responseObserver.onCompleted(); + } +} diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java new file mode 100644 index 0000000000..5235d09318 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.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.testcase.grpc.provider.service; + +import io.grpc.stub.StreamObserver; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; + +public class GreeterServiceImpl extends GreeterGrpc.GreeterImplBase { + + private static final Logger LOGGER = LogManager.getLogger(GreeterServiceImpl.class); + + @Override + public StreamObserver sayHello(final StreamObserver responseObserver) { + StreamObserver requestStreamObserver = new StreamObserver() { + + public void onNext(HelloRequest request) { + LOGGER.info("Receive an message from client. Message: {}", request.getName()); + responseObserver.onNext(HelloReply.newBuilder().setMessage("Hi," + request.getName()).build()); + } + + public void onError(Throwable throwable) { + responseObserver.onError(throwable); + } + + public void onCompleted() { + LOGGER.info("End the stream."); + responseObserver.onCompleted(); + } + }; + return requestStreamObserver; + } +} diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/proto/GreetService.proto b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/proto/GreetService.proto new file mode 100644 index 0000000000..fd5ba4a8f1 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/proto/GreetService.proto @@ -0,0 +1,43 @@ +/* + * 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. + * + */ +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "org.apache.skywalking.apm.testcase.grpc.proto"; + +service Greeter { + rpc SayHello (stream HelloRequest) returns (stream HelloReply) { + } +} + +service GreeterBlocking { + rpc SayHello (HelloRequest) returns (HelloReply) { + } +} +service GreeterBlockingError { + rpc SayHello (HelloRequest) returns (HelloReply) { + } +} + +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; +} \ No newline at end of file diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..37d6d01659 --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +# +# 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 + servlet: + context-path: /grpc-1.59.x-1.70.x-scenario +logging: + config: classpath:log4j2.xml diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/support-version.list b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/support-version.list new file mode 100644 index 0000000000..dd10211b8e --- /dev/null +++ b/test/plugin/scenarios/grpc-1.59.x-1.70.x-scenario/support-version.list @@ -0,0 +1,35 @@ +# 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. + +# INTERNAL: HTTP/2 error code: INTERNAL_ERROR Received Goaway occur in test cases 1.0.0 to 1.5.0 +# So these versions were not included in support-version.list. if you know what caused it, please help us. + +# Contains only the last version number of each minor version + +1.73.0 +1.72.0 +1.71.0 +1.70.0 +1.69.0 +1.68.0 +1.67.1 +1.66.0 +1.65.0 +1.64.0 +1.63.0 +1.62.2 +1.61.0 +1.60.0 From c3a6fcb32b342d39bdf072c0fc8ea853a1aedc47 Mon Sep 17 00:00:00 2001 From: tjuwangning <78459090+tjuwangning@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:35:53 +0800 Subject: [PATCH 069/114] Fix enhanced instance causes Spring Application startup failure (#762) Root cause: SkyWalking's enhancement changes how Spring decides which proxy type to use. As mentioned in [#13221](https://github.com/apache/skywalking/issues/13221#issuecomment-2854170165), SkyWalking modifies Spring's `hasNoUserSuppliedProxyInterfaces()` to avoid affecting the choice of proxy type. But once Spring Retry has added `Retryable` to the list of interfaces, `hasNoUserSuppliedProxyInterfaces()` will find a user-supplied interface and return false, which changes the proxy type and leads to a startup failure. Starting in 4.0.2.RELEASE, Spring adds a new hook method `evaluateProxyInterfaces()`, which allows proxy-related flags (like proxyTargetClass) to be determined earlier in the lifecycle. We also need to enhance `evaluateProxyInterfaces()` (and its related callbacks) so that SkyWalking's EnhancedInstance interface is always ignored. --- CHANGES.md | 2 + .../patch/AutoProxyCreatorInterceptor.java | 53 +++++++++++++ .../ProxyProcessorSupportInterceptor.java | 52 +++++++++++++ .../AutoProxyCreatorInstrumentation.java | 78 +++++++++++++++++++ .../ProxyProcessorSupportInstrumentation.java | 69 ++++++++++++++++ .../src/main/resources/skywalking-plugin.def | 2 + .../scenarios/spring-4.1.x-scenario/pom.xml | 21 +++++ .../testcase/spring3/config/RetryConfig.java | 27 +++++++ .../spring3/service/TestServiceBean.java | 9 +++ 9 files changed, 313 insertions(+) create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/AutoProxyCreatorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/ProxyProcessorSupportInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/AutoProxyCreatorInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/ProxyProcessorSupportInstrumentation.java create mode 100644 test/plugin/scenarios/spring-4.1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/config/RetryConfig.java diff --git a/CHANGES.md b/CHANGES.md index 4f1bc7cee8..116241e4d8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,8 @@ Release Notes. * Support for tracking in lettuce versions 6.5.x and above. * Upgrade byte-buddy version to 1.17.6. * Support gRPC 1.59.x and 1.70.x server interceptor trace +* Fix the `CreateAopProxyInterceptor` in the Spring core-patch changes the AOP proxy type when a class is + enhanced by both SkyWalking and Spring AOP. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/AutoProxyCreatorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/AutoProxyCreatorInterceptor.java new file mode 100644 index 0000000000..943ac8983d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/AutoProxyCreatorInterceptor.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.spring.patch; + +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; + +/** + * AutoProxyCreatorInterceptor determines whether the given interface is {@link EnhancedInstance}, + * and therefore does not consider it a reasonable proxy interface. + */ +public class AutoProxyCreatorInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + + Class ifc = (Class) allArguments[0]; + return ((boolean) ret) || ifc.getName().equals("org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance"); + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/ProxyProcessorSupportInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/ProxyProcessorSupportInterceptor.java new file mode 100644 index 0000000000..d8840d4ef2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/ProxyProcessorSupportInterceptor.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.spring.patch; + +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; + +/** + * ProxyProcessorSupportInterceptor determines whether the given interface is {@link EnhancedInstance}, + * and therefore does not consider it a reasonable proxy interface. + */ +public class ProxyProcessorSupportInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + Class ifc = (Class) allArguments[0]; + return ((boolean) ret) || ifc.getName().equals("org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance"); + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/AutoProxyCreatorInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/AutoProxyCreatorInstrumentation.java new file mode 100644 index 0000000000..26e6147e69 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/AutoProxyCreatorInstrumentation.java @@ -0,0 +1,78 @@ +/* + * 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.spring.patch.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; +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.NameMatch; + +import java.util.Collections; +import java.util.List; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +public class AutoProxyCreatorInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator"; + public static final String ENHANCE_METHOD = "isConfigurationCallbackInterface"; + public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.spring.patch.AutoProxyCreatorInterceptor"; + + @Override + public final ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod(ENHANCE_CLASS, named(ENHANCE_METHOD))); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/ProxyProcessorSupportInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/ProxyProcessorSupportInstrumentation.java new file mode 100644 index 0000000000..78de2969c2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/java/org/apache/skywalking/apm/plugin/spring/patch/define/ProxyProcessorSupportInstrumentation.java @@ -0,0 +1,69 @@ +/* + * 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.spring.patch.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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +public class ProxyProcessorSupportInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.aop.framework.ProxyProcessorSupport"; + public static final String ENHANCE_METHOD = "isInternalLanguageInterface"; + public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.spring.patch.ProxyProcessorSupportInterceptor"; + + @Override + public final ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/resources/skywalking-plugin.def index e51178b97b..3a21d2b4aa 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/src/main/resources/skywalking-plugin.def @@ -19,3 +19,5 @@ spring-core-patch=org.apache.skywalking.apm.plugin.spring.patch.define.Autowired spring-core-patch=org.apache.skywalking.apm.plugin.spring.patch.define.AopExpressionMatchInstrumentation spring-core-patch=org.apache.skywalking.apm.plugin.spring.patch.define.AspectJExpressionPointCutInstrumentation spring-core-patch=org.apache.skywalking.apm.plugin.spring.patch.define.BeanWrapperImplInstrumentation +spring-core-patch=org.apache.skywalking.apm.plugin.spring.patch.define.ProxyProcessorSupportInstrumentation +spring-core-patch=org.apache.skywalking.apm.plugin.spring.patch.define.AutoProxyCreatorInstrumentation diff --git a/test/plugin/scenarios/spring-4.1.x-scenario/pom.xml b/test/plugin/scenarios/spring-4.1.x-scenario/pom.xml index 012ab866eb..b6a8d68bb0 100644 --- a/test/plugin/scenarios/spring-4.1.x-scenario/pom.xml +++ b/test/plugin/scenarios/spring-4.1.x-scenario/pom.xml @@ -33,6 +33,7 @@ 3.8.1 4.1.0.RELEASE spring + 9.4.0 skywalking-spring-4.1.x-scenario @@ -86,6 +87,26 @@ log4j-core 2.8.1 + + org.springframework + spring-aop + ${test.framework.version} + + + org.springframework + spring-aspects + ${test.framework.version} + + + org.springframework.retry + spring-retry + 1.2.5.RELEASE + + + org.apache.skywalking + apm-toolkit-trace + ${apm-toolkit-trace.version} + diff --git a/test/plugin/scenarios/spring-4.1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/config/RetryConfig.java b/test/plugin/scenarios/spring-4.1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/config/RetryConfig.java new file mode 100644 index 0000000000..4d7d40d153 --- /dev/null +++ b/test/plugin/scenarios/spring-4.1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/config/RetryConfig.java @@ -0,0 +1,27 @@ +/* + * 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.spring3.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.retry.annotation.EnableRetry; + +@Configuration +@EnableRetry +public class RetryConfig { +} diff --git a/test/plugin/scenarios/spring-4.1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java b/test/plugin/scenarios/spring-4.1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java index c940d5425c..b99b6b38c3 100644 --- a/test/plugin/scenarios/spring-4.1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java +++ b/test/plugin/scenarios/spring-4.1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java @@ -18,7 +18,10 @@ package test.apache.skywalking.apm.testcase.spring3.service; +import org.apache.skywalking.apm.toolkit.trace.Trace; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.retry.annotation.Backoff; +import org.springframework.retry.annotation.Retryable; import org.springframework.stereotype.Service; import test.apache.skywalking.apm.testcase.spring3.component.TestComponentBean; import test.apache.skywalking.apm.testcase.spring3.dao.TestRepositoryBean; @@ -35,4 +38,10 @@ public void doSomeBusiness(String name) { componentBean.componentMethod(name); repositoryBean.doSomeStuff(name); } + + // Test the class is enhanced by both SkyWalking and Spring AOP + @Retryable(value = Exception.class, backoff = @Backoff(delay = 1000, multiplier = 2)) + @Trace + private void doRetry() { + } } From 77c0de84a47b1300dbbe49c9c3006b94e6516107 Mon Sep 17 00:00:00 2001 From: leeyazhou Date: Tue, 12 Aug 2025 20:51:19 +0800 Subject: [PATCH 070/114] build: fix Checkstyle encoding (#765) - checkstyle's parameter encoding is deprecated since commit (https://github.com/apache/maven-checkstyle-plugin/commit/627fa4f684866a579f2c105fcc1dbf3ed776daa8). - use inputEncoding instead of encoding --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 128d7f6f00..d3ec26bba8 100755 --- a/pom.xml +++ b/pom.xml @@ -396,7 +396,7 @@ ${maven.multiModuleProjectDirectory}/apm-checkstyle/checkStyle.xml ${maven.multiModuleProjectDirectory}/apm-checkstyle/CHECKSTYLE_HEAD - UTF-8 + ${project.build.sourceEncoding} true true ${checkstyle.fails.on.error} From e070270be0f25e006737e087212ddc754c1f8162 Mon Sep 17 00:00:00 2001 From: leeyazhou Date: Fri, 15 Aug 2025 11:07:47 +0800 Subject: [PATCH 071/114] fix: build failure for lombok (#767) fix build failure: ``` [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.10.1:compile (default-compile) on project apm-agent-core: Compilation failure: Compilation failure: [ERROR] /opt/code/git/skywalking-java/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/TraceSegmentRef.java:[51,31] cannot find symbol [ERROR] symbol: method getTraceId() ``` --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index d3ec26bba8..ce52253f22 100755 --- a/pom.xml +++ b/pom.xml @@ -360,6 +360,13 @@ ${compiler.version} ${compiler.version} ${project.build.sourceEncoding} + + + org.projectlombok + lombok + ${lombok.version} + + From 71918d00a6c2aee1e407cd5ae3d5df18301063e6 Mon Sep 17 00:00:00 2001 From: leeyazhou Date: Fri, 15 Aug 2025 13:55:14 +0800 Subject: [PATCH 072/114] (build)version management for maven-pulgin and artifactId (#766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build: Update Maven Plugin Versions and Remove Redundant Declarations • Removed redundant version declarations across modules for `netty` and `junit` • Remove duplicate artifactId declarations `jmh-generator-annprocess` in `apm-sniffer/apm-agent-core/pom.xml` • Centralized plugin (`maven-shade-plugin` and `maven-surefire-plugin` ) version management in the root POM • Centralized `netty` version management in the root POM by add `netty-bom` • (fix)Declare property `maven-docker-plugin.version` --- CHANGES.md | 1 + apm-protocol/apm-network/pom.xml | 3 -- apm-sniffer/apm-agent-core/pom.xml | 7 --- .../httpClient-4.x-plugin/pom.xml | 1 - .../httpclient-5.x-plugin/pom.xml | 1 - apm-sniffer/apm-sdk-plugin/pom.xml | 1 - .../tomcat-7.x-8.x-plugin/pom.xml | 1 - .../websphere-liberty-23.x-plugin/pom.xml | 1 - apm-sniffer/apm-test-tools/pom.xml | 1 - .../netty-http-4.1.x-plugin/pom.xml | 2 - .../gateway-2.0.x-plugin/pom.xml | 1 - .../gateway-2.1.x-plugin/pom.xml | 1 - .../gateway-3.x-plugin/pom.xml | 1 - .../gateway-4.x-plugin/pom.xml | 1 - .../shenyu-2.4.x-plugin/pom.xml | 1 - .../kafka-reporter-plugin/pom.xml | 1 - pom.xml | 53 ++++++++++++++++--- 17 files changed, 47 insertions(+), 31 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 116241e4d8..2049466573 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Release Notes. * Support gRPC 1.59.x and 1.70.x server interceptor trace * Fix the `CreateAopProxyInterceptor` in the Spring core-patch changes the AOP proxy type when a class is enhanced by both SkyWalking and Spring AOP. +* Build: Centralized plugin version management in the root POM and remove redundant declarations. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/apm-protocol/apm-network/pom.xml b/apm-protocol/apm-network/pom.xml index eda94f4e65..7a595eea97 100644 --- a/apm-protocol/apm-network/pom.xml +++ b/apm-protocol/apm-network/pom.xml @@ -35,12 +35,10 @@ io.netty netty-handler-proxy - ${netty.version} io.netty netty-codec-http2 - ${netty.version} io.grpc @@ -75,7 +73,6 @@ io.netty netty-tcnative-boringssl-static - ${netty-tcnative-boringssl-static.version} org.apache.tomcat diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index 19241fcd2c..89fd4b80dc 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -36,7 +36,6 @@ ${project.build.outputDirectory}/skywalking-agent-version.properties 32.0.1-jre 2.6.0 - 2.0.7.Final 1.4.1.Final 4.9.10 com.google @@ -81,7 +80,6 @@ net.bytebuddy byte-buddy-agent - ${bytebuddy.version} test @@ -140,11 +138,6 @@ org.slf4j slf4j-api - - org.openjdk.jmh - jmh-generator-annprocess - test - tools.profiler async-profiler diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml index e2786ece2d..c1a93aceaa 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml @@ -55,7 +55,6 @@ junit junit - ${junit.version} test diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml index 030bace429..1b45528e97 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml @@ -46,7 +46,6 @@ junit junit - ${junit.version} test diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 6c6c30c9d6..36aa71c7ab 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -165,7 +165,6 @@ net.bytebuddy byte-buddy - ${bytebuddy.version} provided diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml index 5a38651fca..cfada90ea7 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml @@ -40,7 +40,6 @@ junit junit - ${junit.version} test diff --git a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml index b0ef592eb7..b15b3b9598 100644 --- a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml @@ -35,7 +35,6 @@ junit junit - ${junit.version} test diff --git a/apm-sniffer/apm-test-tools/pom.xml b/apm-sniffer/apm-test-tools/pom.xml index c9a74371ee..991b95cbb6 100644 --- a/apm-sniffer/apm-test-tools/pom.xml +++ b/apm-sniffer/apm-test-tools/pom.xml @@ -38,7 +38,6 @@ junit junit - ${junit.version} provided diff --git a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml index ca4e3737f7..12866c039c 100644 --- a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml @@ -30,14 +30,12 @@ UTF-8 - 4.1.51.Final io.netty netty-all - ${netty.version} provided diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml index 6ca7443606..feab1be64b 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml @@ -61,7 +61,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 package diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml index 7fd5f57275..a4be9cf053 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml @@ -61,7 +61,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 package diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml index e50550cd3a..93a6e49c66 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml @@ -52,7 +52,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 package diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml index ffa82d61b4..6889f978dd 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml @@ -52,7 +52,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 package diff --git a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml index b76db5ddcd..d5e953f3ba 100644 --- a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml @@ -63,7 +63,6 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 package diff --git a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml index a9ba55cc5a..c831fc0957 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml @@ -137,7 +137,6 @@ org.apache.maven.plugins maven-dependency-plugin - ${maven-dependency-plugin.version} copy diff --git a/pom.xml b/pom.xml index ce52253f22..8576d119f4 100755 --- a/pom.xml +++ b/pom.xml @@ -112,18 +112,19 @@ 2.22.0 3.2.0 3.1.0 - 3.1.1 + 3.2.4 3.0.0-M2 3.10.1 3.1.0 3.0.1 + 3.0.0-M8 2.5 4.3.0 3.2.1 1.33 1.5 true - + 0.46.0 @@ -266,6 +267,23 @@ async-profiler ${async-profiler.version} + + io.netty + netty-bom + ${netty.version} + pom + import + + + io.netty + netty-tcnative-boringssl-static + ${netty-tcnative-boringssl-static.version} + + + io.netty + netty-tcnative-classes + ${netty-tcnative-boringssl-static.version} + @@ -313,6 +331,32 @@ %a-%t-%i + + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + maven-resources-plugin + ${maven-resource-plugin.version} + + + maven-source-plugin + ${maven-source-plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven-dependency-plugin.version} + @@ -331,7 +375,6 @@ maven-enforcer-plugin - ${maven-enforcer-plugin.version} enforce-java @@ -355,7 +398,6 @@ maven-compiler-plugin - ${maven-compiler-plugin.version} ${compiler.version} ${compiler.version} @@ -371,7 +413,6 @@ maven-resources-plugin - ${maven-resource-plugin.version} ${project.build.sourceEncoding} @@ -386,7 +427,6 @@ maven-source-plugin - ${maven-source-plugin.version} attach-sources @@ -461,7 +501,6 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M8 1 false From dcb05fa7350753c66c90989d15ab5e998077d670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Mon, 18 Aug 2025 12:44:27 +0800 Subject: [PATCH 073/114] Release 9.5.0 and start 9.6.0 (#768) --- CHANGES.md | 20 +++------------ .../apm-toolkit-kafka/pom.xml | 2 +- .../apm-toolkit-log4j-1.x/pom.xml | 2 +- .../apm-toolkit-log4j-2.x/pom.xml | 2 +- .../apm-toolkit-logback-1.x/pom.xml | 2 +- .../apm-toolkit-meter/pom.xml | 2 +- .../apm-toolkit-micrometer-1.10/pom.xml | 2 +- .../apm-toolkit-micrometer-registry/pom.xml | 2 +- .../apm-toolkit-opentracing/pom.xml | 2 +- .../apm-toolkit-trace/pom.xml | 2 +- .../apm-toolkit-webflux/pom.xml | 2 +- apm-application-toolkit/pom.xml | 2 +- apm-commons/apm-datacarrier/pom.xml | 2 +- apm-commons/apm-util/pom.xml | 2 +- apm-commons/pom.xml | 2 +- apm-protocol/apm-network/pom.xml | 2 +- apm-protocol/pom.xml | 2 +- apm-sniffer/apm-agent-core/pom.xml | 2 +- apm-sniffer/apm-agent/pom.xml | 2 +- .../activemq-5.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/aerospike-plugin/pom.xml | 2 +- .../apm-armeria-0.84.x-plugin/pom.xml | 2 +- .../apm-armeria-0.85.x-plugin/pom.xml | 2 +- .../apm-armeria-1.0.x-plugin/pom.xml | 2 +- .../apm-armeria-plugins/pom.xml | 2 +- .../asynchttpclient-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/avro-plugin/pom.xml | 2 +- .../baidu-brpc-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/baidu-brpc-plugin/pom.xml | 2 +- .../apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/canal-1.x-plugin/pom.xml | 2 +- .../cassandra-java-driver-3.x-plugin/pom.xml | 2 +- .../clickhouse-0.3.1-plugin/pom.xml | 2 +- .../clickhouse-0.3.2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/cxf-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/dbcp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/druid-1.x-plugin/pom.xml | 2 +- .../dubbo-2.7.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml | 2 +- .../dubbo-3.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-3.x-plugin/pom.xml | 2 +- .../dubbo-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-plugin/pom.xml | 2 +- .../elastic-job-2.x-plugin/pom.xml | 2 +- .../elasticjob-3.x-plugin/pom.xml | 2 +- .../elasticsearch-5.x-plugin/pom.xml | 2 +- .../elasticsearch-6.x-plugin/pom.xml | 2 +- .../elasticsearch-7.x-plugin/pom.xml | 2 +- .../elasticsearch-common/pom.xml | 2 +- .../feign-default-http-9.x-plugin/pom.xml | 2 +- .../finagle-6.25.x-plugin/pom.xml | 2 +- .../graphql-12.x-15.x-plugin/pom.xml | 2 +- .../graphql-16plus-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-8.x-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/graphql-plugin/pom.xml | 2 +- .../grizzly-2.3.x-4.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/grpc-1.x-plugin/pom.xml | 2 +- .../guava-eventbus-plugin/pom.xml | 2 +- .../apm-sdk-plugin/h2-1.x-plugin/pom.xml | 2 +- .../hbase-1.x-2.x-plugin/pom.xml | 2 +- .../hikaricp-3.x-4.x-plugin/pom.xml | 2 +- .../httpClient-4.x-plugin/pom.xml | 2 +- .../httpasyncclient-4.x-plugin/pom.xml | 2 +- .../httpclient-3.x-plugin/pom.xml | 2 +- .../httpclient-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/httpclient-commons/pom.xml | 2 +- .../hutool-http-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/hutool-plugins/pom.xml | 2 +- .../apm-sdk-plugin/hystrix-1.x-plugin/pom.xml | 2 +- .../influxdb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jdbc-commons/pom.xml | 2 +- .../jedis-2.x-3.x-plugin/pom.xml | 2 +- .../jedis-plugins/jedis-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jedis-plugins/pom.xml | 2 +- .../apm-sdk-plugin/jersey-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jersey-3.x-plugin/pom.xml | 2 +- .../jetty-client-11.x-plugin/pom.xml | 2 +- .../jetty-client-9.0-plugin/pom.xml | 2 +- .../jetty-client-9.x-plugin/pom.xml | 2 +- .../jetty-server-11.x-plugin/pom.xml | 2 +- .../jetty-server-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jetty-plugin/pom.xml | 2 +- .../jetty-thread-pool-plugin/pom.xml | 2 +- .../jsonrpc4j-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/kafka-commons/pom.xml | 2 +- .../apm-sdk-plugin/kafka-plugin/pom.xml | 2 +- .../kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml | 2 +- .../lettuce-5.x-6.4.x-plugin/pom.xml | 6 ++--- .../lettuce-6.5.x-plugin/pom.xml | 6 ++--- .../lettuce-plugins/lettuce-common/pom.xml | 6 ++--- .../apm-sdk-plugin/lettuce-plugins/pom.xml | 6 ++--- .../light4j-plugins/light4j-plugin/pom.xml | 2 +- .../apm-sdk-plugin/light4j-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mariadb-2.x-plugin/pom.xml | 2 +- .../micronaut-http-client-plugin/pom.xml | 2 +- .../micronaut-http-server-plugin/pom.xml | 2 +- .../apm-sdk-plugin/micronaut-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/motan-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mssql-commons/pom.xml | 2 +- .../apm-sdk-plugin/mssql-jdbc-plugin/pom.xml | 2 +- .../mssql-jtds-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-6.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-common/pom.xml | 2 +- .../nats-2.14.x-2.16.5-plugin/pom.xml | 2 +- .../apm-sdk-plugin/neo4j-4.x-plugin/pom.xml | 2 +- .../netty-socketio-plugin/pom.xml | 2 +- .../nutz-plugins/http-1.x-plugin/pom.xml | 2 +- .../mvc-annotation-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/nutz-plugins/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-common/pom.xml | 2 +- .../apm-sdk-plugin/play-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-sdk-plugin/pom.xml | 2 +- .../postgresql-8.x-plugin/pom.xml | 2 +- .../pulsar-2.2-2.7-plugin/pom.xml | 2 +- .../pulsar-2.8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/pulsar-common/pom.xml | 2 +- .../apm-sdk-plugin/quasar-plugin/pom.xml | 2 +- .../apm-sdk-plugin/rabbitmq-plugin/pom.xml | 2 +- .../redisson-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/resteasy-plugin/pom.xml | 2 +- .../resteasy-server-3.x-plugin/pom.xml | 2 +- .../resteasy-server-4.x-plugin/pom.xml | 2 +- .../resteasy-server-6.x-plugin/pom.xml | 2 +- .../rocketMQ-3.x-plugin/pom.xml | 2 +- .../rocketMQ-4.x-plugin/pom.xml | 2 +- .../rocketMQ-5.x-plugin/pom.xml | 2 +- .../rocketMQ-client-java-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/servicecomb-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../shardingsphere-plugins/pom.xml | 2 +- .../sharding-sphere-3.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.0.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.1.0-plugin/pom.xml | 2 +- .../sharding-sphere-5.0.0-plugin/pom.xml | 2 +- .../apm-sdk-plugin/sofarpc-plugin/pom.xml | 2 +- .../apm-sdk-plugin/solon-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/solrj-7.x-plugin/pom.xml | 2 +- .../async-annotation-plugin/pom.xml | 2 +- .../concurrent-util-4.x-plugin/pom.xml | 2 +- .../spring-plugins/core-patch/pom.xml | 2 +- .../mvc-annotation-3.x-plugin/pom.xml | 2 +- .../mvc-annotation-4.x-plugin/pom.xml | 2 +- .../mvc-annotation-5.x-plugin/pom.xml | 2 +- .../mvc-annotation-commons/pom.xml | 2 +- .../apm-sdk-plugin/spring-plugins/pom.xml | 2 +- .../resttemplate-3.x-plugin/pom.xml | 2 +- .../resttemplate-4.x-plugin/pom.xml | 2 +- .../resttemplate-commons/pom.xml | 2 +- .../scheduled-annotation-plugin/pom.xml | 2 +- .../spring-cloud/netflix-plugins/pom.xml | 2 +- .../spring-cloud-feign-1.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-cloud/pom.xml | 2 +- .../spring-cloud-feign-2.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-commons/pom.xml | 2 +- .../spring-kafka-1.x-plugin/pom.xml | 2 +- .../spring-kafka-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../spymemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/struts2-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/thrift-plugin/pom.xml | 2 +- .../apm-sdk-plugin/tomcat-10x-plugin/pom.xml | 2 +- .../tomcat-7.x-8.x-plugin/pom.xml | 2 +- .../tomcat-thread-pool-plugin/pom.xml | 2 +- .../apm-sdk-plugin/undertow-plugins/pom.xml | 2 +- .../undertow-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/vertx-plugins/pom.xml | 2 +- .../vertx-core-3.x-plugin/pom.xml | 2 +- .../vertx-core-4.x-plugin/pom.xml | 2 +- .../websphere-liberty-23.x-plugin/pom.xml | 2 +- .../xmemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-test-tools/pom.xml | 2 +- .../apm-toolkit-kafka-activation/pom.xml | 2 +- .../apm-toolkit-log4j-1.x-activation/pom.xml | 2 +- .../apm-toolkit-log4j-2.x-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-logging-common/pom.xml | 2 +- .../apm-toolkit-meter-activation/pom.xml | 2 +- .../apm-toolkit-micrometer-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-trace-activation/pom.xml | 2 +- .../apm-toolkit-webflux-activation/pom.xml | 2 +- apm-sniffer/apm-toolkit-activation/pom.xml | 2 +- .../jdk-forkjoinpool-plugin/pom.xml | 2 +- .../bootstrap-plugins/jdk-http-plugin/pom.xml | 2 +- .../jdk-threading-plugin/pom.xml | 2 +- .../jdk-threadpool-plugin/pom.xml | 2 +- .../pom.xml | 2 +- apm-sniffer/bootstrap-plugins/pom.xml | 2 +- apm-sniffer/bytebuddy-patch/pom.xml | 2 +- .../impala-jdbc-2.6.x-plugin/pom.xml | 2 +- apm-sniffer/expired-plugins/pom.xml | 2 +- .../caffeine-3.x-plugin/pom.xml | 2 +- .../customize-enhance-plugin/pom.xml | 2 +- .../ehcache-2.x-plugin/pom.xml | 2 +- .../fastjson-1.2.x-plugin/pom.xml | 2 +- .../gson-2.8.x-plugin/pom.xml | 2 +- .../guava-cache-plugin/pom.xml | 2 +- .../jackson-2.x-plugin/pom.xml | 2 +- .../kotlin-coroutine-plugin/pom.xml | 2 +- .../mybatis-3.x-plugin/pom.xml | 2 +- .../nacos-client-2.x-plugin/pom.xml | 2 +- .../netty-http-4.1.x-plugin/pom.xml | 2 +- .../mvc-annotation-6.x-plugin/pom.xml | 2 +- .../gateway-2.0.x-plugin/pom.xml | 2 +- .../gateway-2.1.x-plugin/pom.xml | 2 +- .../gateway-3.x-plugin/pom.xml | 2 +- .../gateway-4.x-plugin/pom.xml | 2 +- .../optional-spring-cloud/pom.xml | 2 +- .../optional-spring-plugins/pom.xml | 2 +- .../resttemplate-6.x-plugin/pom.xml | 2 +- .../spring-annotation-plugin/pom.xml | 2 +- .../spring-tx-plugin/pom.xml | 2 +- .../spring-webflux-5.x-plugin/pom.xml | 2 +- .../spring-webflux-6.x-plugin/pom.xml | 2 +- apm-sniffer/optional-plugins/pom.xml | 2 +- .../quartz-scheduler-2.x-plugin/pom.xml | 2 +- .../sentinel-1.x-plugin/pom.xml | 2 +- .../shenyu-2.4.x-plugin/pom.xml | 2 +- .../trace-ignore-plugin/pom.xml | 2 +- .../trace-sampler-cpu-policy-plugin/pom.xml | 2 +- .../zookeeper-3.4.x-plugin/pom.xml | 2 +- .../kafka-config-extension/pom.xml | 2 +- .../kafka-reporter-plugin/pom.xml | 2 +- apm-sniffer/optional-reporter-plugins/pom.xml | 2 +- apm-sniffer/pom.xml | 2 +- changes/changes-9.5.0.md | 25 +++++++++++++++++++ pom.xml | 2 +- 241 files changed, 271 insertions(+), 268 deletions(-) create mode 100644 changes/changes-9.5.0.md diff --git a/CHANGES.md b/CHANGES.md index 2049466573..de2ded2867 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,26 +2,12 @@ Changes by Version ================== Release Notes. -9.5.0 +9.6.0 ------------------ -* Add the virtual thread executor plugin -* Fix Conflicts apm-jdk-threadpool-plugin conflicts with apm-jdk-forkjoinpool-plugin -* Fix NPE in hikaricp-plugin if JDBC URL is not set -* Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent transfer - initialization. Delay so11y metrics#build when the services are not ready to avoid MeterService status is not - initialized. -* Fix retransform failure when enhancing both parent and child classes. -* Add support for `dameng(DM)` JDBC url format in `URLParser`. -* Fix RabbitMQ Consumer could not receive handleCancelOk callback. -* Support for tracking in lettuce versions 6.5.x and above. -* Upgrade byte-buddy version to 1.17.6. -* Support gRPC 1.59.x and 1.70.x server interceptor trace -* Fix the `CreateAopProxyInterceptor` in the Spring core-patch changes the AOP proxy type when a class is - enhanced by both SkyWalking and Spring AOP. -* Build: Centralized plugin version management in the root POM and remove redundant declarations. -All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) ------------------ Find change logs of all versions [here](changes). diff --git a/apm-application-toolkit/apm-toolkit-kafka/pom.xml b/apm-application-toolkit/apm-toolkit-kafka/pom.xml index 7c3716b0e5..05365ce572 100644 --- a/apm-application-toolkit/apm-toolkit-kafka/pom.xml +++ b/apm-application-toolkit/apm-toolkit-kafka/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml index cb8993d17c..e2b12f7171 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml index 1c3d85a7fe..3b0ecb2103 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml index 7c5a107738..f7f441bde3 100644 --- a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-meter/pom.xml b/apm-application-toolkit/apm-toolkit-meter/pom.xml index 30d8dcf028..b5d212c20c 100644 --- a/apm-application-toolkit/apm-toolkit-meter/pom.xml +++ b/apm-application-toolkit/apm-toolkit-meter/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml index 8a266900ab..b570a7fda8 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml index 424c5af99c..8c972efdc2 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml index 121ce32141..5d0dc02d38 100644 --- a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml +++ b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-trace/pom.xml b/apm-application-toolkit/apm-toolkit-trace/pom.xml index 89e24e7416..5b186af0d9 100644 --- a/apm-application-toolkit/apm-toolkit-trace/pom.xml +++ b/apm-application-toolkit/apm-toolkit-trace/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-webflux/pom.xml b/apm-application-toolkit/apm-toolkit-webflux/pom.xml index 8320b65eac..2dab4fc7ea 100644 --- a/apm-application-toolkit/apm-toolkit-webflux/pom.xml +++ b/apm-application-toolkit/apm-toolkit-webflux/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/pom.xml b/apm-application-toolkit/pom.xml index 360309be0f..e004d63b06 100644 --- a/apm-application-toolkit/pom.xml +++ b/apm-application-toolkit/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 apm-application-toolkit diff --git a/apm-commons/apm-datacarrier/pom.xml b/apm-commons/apm-datacarrier/pom.xml index 83c7bd6026..fd0cbf6280 100644 --- a/apm-commons/apm-datacarrier/pom.xml +++ b/apm-commons/apm-datacarrier/pom.xml @@ -21,7 +21,7 @@ java-agent-commons org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/apm-util/pom.xml b/apm-commons/apm-util/pom.xml index e2ed3c0faf..bf1169bfde 100644 --- a/apm-commons/apm-util/pom.xml +++ b/apm-commons/apm-util/pom.xml @@ -20,7 +20,7 @@ java-agent-commons org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/pom.xml b/apm-commons/pom.xml index 54d6c00fbe..3b54179ebe 100644 --- a/apm-commons/pom.xml +++ b/apm-commons/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/apm-network/pom.xml b/apm-protocol/apm-network/pom.xml index 7a595eea97..9964486b65 100644 --- a/apm-protocol/apm-network/pom.xml +++ b/apm-protocol/apm-network/pom.xml @@ -21,7 +21,7 @@ java-agent-protocol org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/pom.xml b/apm-protocol/pom.xml index b71653c24a..10be0c6791 100644 --- a/apm-protocol/pom.xml +++ b/apm-protocol/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index 89fd4b80dc..f4a7350214 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-agent-core diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 9429528a9b..07cdd3e195 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-agent diff --git a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml index 55fef10c59..19d0a0ac07 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml index 3985b5397c..da27f49425 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml index 92d9f01a3b..9dfc94d3f0 100644 --- a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml index 2ac5d6da16..fee4c87555 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml index b7828f4736..bd33a3f2de 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml index 8e697d2f94..2e711d08f1 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml index db15e7eede..d3bb98f95c 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml index ec7c1edfcb..5b9862e235 100644 --- a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml index 0007f48f52..e58c105c66 100644 --- a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml index e5bc1cc77b..a9a5903d55 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml index 1c4f31078e..96e05ed0c8 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml index b82413193c..a6d5abaa51 100644 --- a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml index a1345ce94b..143239cf4c 100644 --- a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml index 3f18e7dd91..f710b489eb 100644 --- a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml index a02c6c825b..a669888e52 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml index 12f4545553..f02f4b7c73 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml index 142a1af779..93f8952933 100644 --- a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml index c5d9f1c622..7e073160b5 100644 --- a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml index b6d66a13c2..9b236f308f 100644 --- a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml index 250b40747f..0e9cee5454 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml index e09e68f0e9..0c98cc6695 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml index c45ce3088b..c092225837 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml index 23a54b3dea..02d82c2341 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml index 14d0c6dd8e..744e911633 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml index 7f3f74e7e4..a83f02078c 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml index 9ca6fa2a0b..0d12e32ca6 100644 --- a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml index 4a1104df96..065469ee06 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml index 66158a23c6..e2862daf57 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml index e0498309df..a727f273ee 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml index 23d01d02b6..1e22dbef16 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml index fe073bab48..1e43afaef4 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml index cb61046af8..77b513f56b 100644 --- a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml index ff67ed2756..d65f65cbb6 100644 --- a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml index 4aaeb95e96..9a0b7824df 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml index 16f50fca6b..2fe40768a5 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml index b2007ad0c3..6de13ee103 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml index 5214288cc1..4fef19e90f 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml index 9ae21f8860..ebbeb91191 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml index a659f766be..9b650f7cd9 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml index fb58ba4b09..84699cac8b 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-grizzly-2.x-4.x-work-threadpool-plugin diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml index b1fc5775ae..12f7b140d8 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-grpc-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml index e17161bf7e..678218e2ba 100644 --- a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml index 8c50a7eb03..ad985a3ee7 100755 --- a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml index 77b14b76b1..2809352c1b 100644 --- a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-hbase-1.x-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml index 348d7a23bb..330c7bcf37 100644 --- a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml index c1a93aceaa..00d5f64d55 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-httpClient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml index a59dde7d37..6b60405e18 100644 --- a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-httpasyncclient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml index befc85cd6e..3203867e3a 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-httpclient-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml index 1b45528e97..f1a047e813 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-httpclient-5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml index 32f90e5522..37bedce74c 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-httpclient-commons diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml index 1e469dd79c..9ff2019872 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ hutool-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml index ac5912a1d5..92249a85a5 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml index a6a0b0bc03..ba9914c170 100644 --- a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml index d0d31dc340..f9e47326cf 100644 --- a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml index b665da8275..46759160e6 100755 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml index 540074e372..9da30b3367 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking jedis-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml index 8527b72e9b..3b72ba9d1b 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ jedis-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml index fa0049c0a4..8b58716509 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT diff --git a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml index 19695c5449..8d9f6824b1 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml index fafc35d46a..0524344fdd 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml index 49f4b892af..79ffd36ac4 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml index 911028beea..0d7545a5f2 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml index 8765b520cc..6b92929f8b 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml index 7210f0e51c..a5d993b031 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml index 85f58596a8..17049eadd7 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml index b0625e34f5..230c49aff0 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT jetty-plugins diff --git a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml index f3befb3a02..db583d1800 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml index b3575f408e..b0d5740694 100644 --- a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml index 56f7535d9d..322b7fc81b 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-kafka-commons diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml index 44cdcc8a48..1e3f0588a4 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml index 35f9c49d78..4bff437545 100644 --- a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml index 538e68074c..facce0452d 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml @@ -17,14 +17,12 @@ ~ --> - + 4.0.0 org.apache.skywalking lettuce-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-lettuce-5.x-6.4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml index d962ade037..1e4461f495 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml @@ -17,14 +17,12 @@ ~ --> - + 4.0.0 org.apache.skywalking lettuce-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-lettuce-6.5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml index 142e7f4541..463250cf39 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml @@ -17,14 +17,12 @@ ~ --> - + 4.0.0 org.apache.skywalking lettuce-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-lettuce-common diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml index aba6387406..c9cfe8d17c 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml @@ -17,14 +17,12 @@ ~ --> - + 4.0.0 org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT lettuce-plugins diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml index 82ec21b53e..5785ce44cd 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml @@ -20,7 +20,7 @@ light4j-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml index 940a6cc9d3..1d8da85b79 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT light4j-plugins diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml index 88aaaa4f20..802ed1f44c 100644 --- a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml index df3c7fc819..dfd0f426bb 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml index a97560446d..4d7e5f56de 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml index 7c2f4c9153..89fb218808 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml index 87d6518afe..1f2e130efb 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml index 6181f336e0..6ff822a4a0 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-mongodb-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml index 903fe7e6f1..de38fedcae 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-mongodb-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml index 74f25bdc82..d3319b9cdb 100644 --- a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml index bfea14ea91..441bf6601d 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml index 9129842df7..13d0cb16ff 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml index 05cc1cc520..04687dbcc1 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml index 0e567b465c..ee171e5c32 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml index dfb7c3927c..1e07e995b8 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml index 4b72ab25d6..b84115d907 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml index ab027cc967..c832784e25 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml index 61ffd1e302..2d85d4cd9b 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml index 687c26c0c1..0b98a3efe2 100644 --- a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml index a90718c960..5c8a854b9b 100644 --- a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml index b09d263257..d1fe436ea6 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml index 633775692b..2f968d2bf5 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml index cf6619cce9..711786d120 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT nutz-plugins diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml index ca6b0f410c..ede53c4ff8 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml index 4440fb707d..ef6fcb0239 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml index c1d3854825..a8d0a42612 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml index f3588227a6..96d60b3765 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml index 1e96e2c0b6..26491de16c 100644 --- a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-play-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 36aa71c7ab..ea21985349 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking java-agent-sniffer - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-sdk-plugin diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml index bfccc6c6dc..4ce5b69ecd 100755 --- a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml index 85eea26033..98a45766bb 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml index 7398535cdc..fbe2c3fe00 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml index 555be168e9..7fa0685161 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml index 77a4db4d95..99bd15fb4f 100644 --- a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-quasar-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml index c8add46003..65f78a5467 100644 --- a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml index 8f1c0c959a..55edbdeac3 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-redisson-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml index e00a66d323..6ff7caaaaa 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT resteasy-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml index 845ba79186..14d989003f 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT resteasy-server-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml index d4a2f6fac5..f21d450b6a 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT resteasy-server-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml index 653cac9f96..f259291bfd 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT resteasy-server-6.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml index 24b5e08ca1..6b206013d9 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml index 091d0d2c8e..6fa277b4ef 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml index e25561ad98..ad51da8c77 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml index 2e0cb1a88c..d07527b994 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml index d416b50a87..e010d7cc09 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml index a423494f0b..f92f636768 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ servicecomb-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml index a5d3febb25..60d101c987 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml index d630c327fe..48776bf7e7 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml index 969e0d71f9..cdbdf13335 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml index 6378eb83b5..99b838e1e7 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml index 057f200f8a..013e5929ed 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml index abd34c6675..c685c69dd7 100644 --- a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml index 305501d2d6..5221d63d04 100644 --- a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT solon-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml index e39497748f..f8b02211f4 100644 --- a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml index dd621bb928..556c7f269a 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml index c80e8a2e37..8c922b6c28 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml index e99e3c78e7..0b367dffe7 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml index 9c5e1083d4..a3ad988877 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml index 8081633e00..d551f811a0 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml index 90da81f340..c8eae36531 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml @@ -19,7 +19,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml index d439f9f138..67bcaaac46 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml index 9f03ceb189..10b0268892 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT spring-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml index 8090108737..2b8cb9beed 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml index 0f93f494f3..9bcaa96cbf 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml index 7d595c3990..7317ad938a 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml index b2a8839a14..3bb2740074 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml index fcbef61d3d..7df17507ae 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT netflix-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml index 51d577a2b2..4a76383083 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking netflix-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-spring-cloud-feign-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml index 50bb2fc000..19d050291c 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT spring-cloud diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml index 268c60f4d3..bd7a6d2f3f 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-spring-cloud-feign-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml index 10764dce33..7e1ff15179 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml index 4f88e7dd08..a8afa0c54a 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-spring-kafka-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml index 8268920161..267f56a506 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-spring-kafka-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml index 302a39ffa5..2c818ab342 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml index 3c613e71fc..6d50169112 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml index 48a234f1c5..4eda0fae4c 100644 --- a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-spymemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml index 6b4ed9b5a9..9e164a9477 100644 --- a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml index ff6eb323ba..c481a809ef 100644 --- a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml index 59e4fa7ccf..ca896b0cef 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml index cfada90ea7..7307cd3f9a 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml index 81751b7e30..7c5eb5597b 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml index de51de6721..10a4132bfd 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT undertow-plugins diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml index 68bfbbf7ea..952be80876 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ undertow-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml index 12c14420d4..a46b602982 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml index 8ee54e78b7..a33ebb009e 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT vertx-plugins diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml index 7677806266..1a33046229 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml index f47dcf2da0..981b6bdd3d 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml index b15b3b9598..4d1971ea07 100644 --- a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml index 4e4df94336..fa896a48e2 100644 --- a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-xmemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml index 88e8223ae4..5566ea223c 100644 --- a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-test-tools/pom.xml b/apm-sniffer/apm-test-tools/pom.xml index 991b95cbb6..8b406e428e 100644 --- a/apm-sniffer/apm-test-tools/pom.xml +++ b/apm-sniffer/apm-test-tools/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-test-tools diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml index eb9bd221e1..c14b96205e 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml index 2a71222db5..b3a5651b21 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml index 00938c5768..747d520d74 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml index 3fc275601b..75b3b31866 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml index 22079cb1a7..57033d5b09 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml index 44838ec361..c04acb613b 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml index a3510d1c36..fb6e91be34 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml index 0b654a04ed..a260c73ed8 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml index 85caf42f41..e0d378caea 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml index ea1208fcaa..b82def92b1 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/pom.xml index 13a2b11abc..09206213e1 100644 --- a/apm-sniffer/apm-toolkit-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml index 8519bb6f76..94de5b8c2a 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml index c121b39605..e1970ec4da 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml index be2ea6621a..6bed3de12b 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml index 3f3f7fda66..ca7eb8cac7 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml @@ -20,7 +20,7 @@ bootstrap-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml index 705560aad1..67766ef3eb 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml @@ -20,7 +20,7 @@ bootstrap-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/pom.xml b/apm-sniffer/bootstrap-plugins/pom.xml index 22de027237..8d1424343c 100644 --- a/apm-sniffer/bootstrap-plugins/pom.xml +++ b/apm-sniffer/bootstrap-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bytebuddy-patch/pom.xml b/apm-sniffer/bytebuddy-patch/pom.xml index 9891184099..60b20cffe9 100644 --- a/apm-sniffer/bytebuddy-patch/pom.xml +++ b/apm-sniffer/bytebuddy-patch/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking java-agent-sniffer - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml index 1e73ce957f..5ac2465450 100644 --- a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml +++ b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml @@ -24,7 +24,7 @@ org.apache.skywalking expired-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-impala-jdbc-2.6.x-plugin diff --git a/apm-sniffer/expired-plugins/pom.xml b/apm-sniffer/expired-plugins/pom.xml index f05ba0911c..f33497cec5 100644 --- a/apm-sniffer/expired-plugins/pom.xml +++ b/apm-sniffer/expired-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml index 3b1a717fb1..8428e0e60e 100644 --- a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-caffeine-3.x-plugin diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml index 56e06888fd..14fc75ee0e 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml index ee76290141..9dea5174c9 100644 --- a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml index 5308320d5d..630524d970 100644 --- a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-fastjson-1.x-plugin diff --git a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml index a328a8d4df..f45e92d2f5 100644 --- a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-gson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml index 45653d891a..e32c47ce81 100644 --- a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-guava-cache-plugin diff --git a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml index 35228a0af8..1b1d26a818 100644 --- a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-jackson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml index b029145a05..0f55f43e47 100644 --- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-kotlin-coroutine-plugin diff --git a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml index c66c1e6919..84ba662bcf 100644 --- a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-mybatis-3.x-plugin diff --git a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml index 2c8279b547..acbd852ce7 100644 --- a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml index 12866c039c..daeacb30d2 100644 --- a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml index b6972d435d..b7f5b84a75 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml @@ -19,7 +19,7 @@ optional-spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml index feab1be64b..b798e59499 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-spring-cloud-gateway-2.0.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml index a4be9cf053..e5b6e7e100 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-spring-cloud-gateway-2.1.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml index 93a6e49c66..5bfe88aef2 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml index 6889f978dd..d890c84e7c 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml index a884700ba6..281fb79f0e 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT optional-spring-cloud diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml index 71e1f715f2..344126cd75 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml index 772211aa4d..18d0a3037c 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ optional-spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml index d43d45a461..e943d2451c 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml index 77ef74f7bb..f03fd451c0 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml index 7674b94aee..2ef8246634 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml index 0272715a1a..ca9e22a8d0 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml index d5c31745e7..143a79f94b 100644 --- a/apm-sniffer/optional-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml index f7c6a7559c..ab9894e133 100644 --- a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-quartz-scheduler-2.x-plugin diff --git a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml index cffef0e57e..c3c4a2f162 100644 --- a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml index d5e953f3ba..10f4d208fa 100644 --- a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml index 2c4c16d8e8..32d5002b57 100644 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml index 7b3b9198eb..b2dfdfdfe9 100644 --- a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml index 4b85b133fc..723e675445 100644 --- a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT apm-zookeeper-3.4.x-plugin diff --git a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml index b17f873159..15026e49df 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml @@ -20,7 +20,7 @@ optional-reporter-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml index c831fc0957..99b9cf3679 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml @@ -21,7 +21,7 @@ optional-reporter-plugins org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/pom.xml b/apm-sniffer/optional-reporter-plugins/pom.xml index 0180b036d0..32700b16af 100644 --- a/apm-sniffer/optional-reporter-plugins/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/pom.xml b/apm-sniffer/pom.xml index 3908e24a0d..4cb926b474 100644 --- a/apm-sniffer/pom.xml +++ b/apm-sniffer/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT 4.0.0 diff --git a/changes/changes-9.5.0.md b/changes/changes-9.5.0.md new file mode 100644 index 0000000000..ff5133d250 --- /dev/null +++ b/changes/changes-9.5.0.md @@ -0,0 +1,25 @@ +Changes by Version +================== +Release Notes. + +9.5.0 +------------------ + +* Add the virtual thread executor plugin +* Fix Conflicts apm-jdk-threadpool-plugin conflicts with apm-jdk-forkjoinpool-plugin +* Fix NPE in hikaricp-plugin if JDBC URL is not set +* Agent kernel services could be not-booted-yet as ServiceManager#INSTANCE#boot executed after agent transfer + initialization. Delay so11y metrics#build when the services are not ready to avoid MeterService status is not + initialized. +* Fix retransform failure when enhancing both parent and child classes. +* Add support for `dameng(DM)` JDBC url format in `URLParser`. +* Fix RabbitMQ Consumer could not receive handleCancelOk callback. +* Support for tracking in lettuce versions 6.5.x and above. +* Upgrade byte-buddy version to 1.17.6. +* Support gRPC 1.59.x and 1.70.x server interceptor trace +* Fix the `CreateAopProxyInterceptor` in the Spring core-patch changes the AOP proxy type when a class is + enhanced by both SkyWalking and Spring AOP. +* Build: Centralized plugin version management in the root POM and remove redundant declarations. + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) + diff --git a/pom.xml b/pom.xml index 8576d119f4..ebaa942c17 100755 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent - 9.5.0-SNAPSHOT + 9.6.0-SNAPSHOT org.apache From f1da117722e314f01ea8d182a2bce4a79f45f0fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Thu, 21 Aug 2025 00:18:53 +0800 Subject: [PATCH 074/114] Bump up dependencies and e2e (#770) * Bump up agent-oap protocol to latest(16c51358ebcf42629bf4ffdf952253971f20eb25). * Bump up gRPC to v1.74.0. * Bump up Netty to v4.1.124.Final. * Bump up GSON to v2.13.1. * Bump up guava to v32.1.3. * Bump up oap to the 10.3-dev.latest(dc8740d4757b35374283c4850a9a080e40f0eb79) in e2e. * Bump up cli to the 0.15.0-dev.latest(77b4c49e89c9c000278f44e62729d534f2ec842e) in e2e. * Support for uploading logs of e2e. --- .github/workflows/e2e.yaml | 10 +++++++-- CHANGES.md | 8 ++++++- apm-protocol/apm-network/src/main/proto | 2 +- apm-sniffer/apm-agent-core/pom.xml | 2 -- dist-material/LICENSE | 10 ++++----- pom.xml | 14 ++++++++----- test/e2e/base/base-compose.yml | 20 ++++++++++++++++-- test/e2e/base/pom.xml | 2 +- test/e2e/case/expected/event-list.yml | 4 ++-- test/e2e/case/expected/logs-list.yml | 3 ++- test/e2e/case/expected/metrics-has-value.yml | 12 +++++++---- test/e2e/case/expected/service.yml | 21 ++++++++++++++++++- test/e2e/case/expected/trace-info-detail.yml | 2 ++ test/e2e/case/expected/trace-users-detail.yml | 2 ++ test/e2e/case/expected/traces-list.yml | 20 ++++++++---------- test/e2e/case/grpc/docker-compose.yml | 7 +++++++ test/e2e/case/kafka/docker-compose.yml | 7 +++++++ test/e2e/script/env | 4 +++- test/e2e/script/prepare/install-swctl.sh | 18 ++++++++++------ 19 files changed, 123 insertions(+), 45 deletions(-) diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 99059989a0..dc595bc85c 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -58,8 +58,14 @@ jobs: - name: Setup go uses: actions/setup-go@v2 with: - go-version: '1.18' + go-version: '1.24' - name: Run E2E Tests - uses: apache/skywalking-infra-e2e@cf589b4a0b9f8e6f436f78e9cfd94a1ee5494180 + uses: apache/skywalking-infra-e2e@7e4b5b68716fdb7b79b21fa8908f9db497e1b115 with: e2e-file: ${{ matrix.case.path }} + - uses: actions/upload-artifact@v4 + if: ${{ failure() }} + name: Upload Logs + with: + name: test-logs-${{ matrix.case.name }} + path: "${{ env.SW_INFRA_E2E_LOG_DIR }}" diff --git a/CHANGES.md b/CHANGES.md index de2ded2867..8140e6c5d7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,13 @@ Release Notes. 9.6.0 ------------------ - +* Bump up agent-oap protocol to latest(16c51358ebcf42629bf4ffdf952253971f20eb25). +* Bump up gRPC to v1.74.0. +* Bump up netty to v4.1.124.Final. +* Bump up GSON to v2.13.1. +* Bump up guava to v32.1.3. +* Bump up oap to the 10.3-dev.latest(dc8740d4757b35374283c4850a9a080e40f0eb79) in e2e. +* Bump up cli to the 0.15.0-dev.latest(77b4c49e89c9c000278f44e62729d534f2ec842e) in e2e. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/apm-protocol/apm-network/src/main/proto b/apm-protocol/apm-network/src/main/proto index bd1f91f7e1..16c51358eb 160000 --- a/apm-protocol/apm-network/src/main/proto +++ b/apm-protocol/apm-network/src/main/proto @@ -1 +1 @@ -Subproject commit bd1f91f7e1cb4de9d9b5ccb71f36ce6b1c7c97f5 +Subproject commit 16c51358ebcf42629bf4ffdf952253971f20eb25 diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index f4a7350214..d251748fe3 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -34,9 +34,7 @@ UTF-8 ${project.build.outputDirectory}/skywalking-agent-version.properties - 32.0.1-jre 2.6.0 - 1.4.1.Final 4.9.10 com.google ${shade.package}.${shade.com.google.source} diff --git a/dist-material/LICENSE b/dist-material/LICENSE index e261fd20da..a7cb7efaeb 100755 --- a/dist-material/LICENSE +++ b/dist-material/LICENSE @@ -216,12 +216,12 @@ The following components are provided under the Apache License. See project link The text of each license is the standard Apache 2.0 license. raphw (byte-buddy) 1.17.6: http://bytebuddy.net/ , Apache 2.0 - Google: grpc-java 1.68.1: https://github.com/grpc/grpc-java, Apache 2.0 - Google: gson 2.8.9: https://github.com/google/gson , Apache 2.0 - Google: proto-google-common-protos 2.0.1: https://github.com/googleapis/googleapis , Apache 2.0 + Google: grpc-java 1.74.0: https://github.com/grpc/grpc-java, Apache 2.0 + Google: gson 2.13.1: https://github.com/google/gson , Apache 2.0 + Google: proto-google-common-protos 2.59.2: https://github.com/googleapis/googleapis , Apache 2.0 Google: jsr305 3.0.2: http://central.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.0/jsr305-3.0.0.pom , Apache 2.0 - Google: guava 32.0.1: https://github.com/google/guava , Apache 2.0 - netty 4.1.115: https://github.com/netty/netty/blob/4.1/LICENSE.txt, Apache 2.0 + Google: guava 32.1.3: https://github.com/google/guava , Apache 2.0 + netty 4.1.124: https://github.com/netty/netty/blob/4.1/LICENSE.txt, Apache 2.0 async-profiler 3.0: https://github.com/async-profiler/async-profiler/blob/v3.0/LICENSE, Apache 2.0 ======================================================================== diff --git a/pom.xml b/pom.xml index ebaa942c17..abeaac8ced 100755 --- a/pom.xml +++ b/pom.xml @@ -87,14 +87,18 @@ 1.17.6 - 1.68.1 - 4.1.115.Final - 2.8.9 + 1.74.0 + 4.1.124.Final + 2.13.1 + + + 32.1.3-jre + 1.7.1 0.6.1 3.25.5 - 1.68.1 - 2.0.48.Final + 1.74.0 + 2.0.70.Final 1.3.2 3.1 3.0 diff --git a/test/e2e/base/base-compose.yml b/test/e2e/base/base-compose.yml index e6b4b70c4b..f25eb8ce25 100644 --- a/test/e2e/base/base-compose.yml +++ b/test/e2e/base/base-compose.yml @@ -18,7 +18,7 @@ version: '2.1' services: oap: - image: ghcr.io/apache/skywalking/oap:1730f2c84bbd4da999ec2c74d1c26db31d5a0d24 + image: "ghcr.io/apache/skywalking/oap:${SW_OAP_COMMIT}" expose: - 11800 - 12800 @@ -26,7 +26,23 @@ services: - e2e restart: on-failure healthcheck: - test: ["CMD", "sh", "-c", "nc -zn 127.0.0.1 11800"] + test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/11800" ] + interval: 5s + timeout: 60s + retries: 120 + environment: + SW_STORAGE_BANYANDB_TARGETS: banyandb:17912 + + banyandb: + image: "ghcr.io/apache/skywalking-banyandb:${SW_BANYANDB_COMMIT}" + networks: + - e2e + ports: + - 17912:17912 + - 17913:17913 + command: standalone --stream-root-path /tmp/stream-data --measure-root-path /tmp/measure-data --measure-metadata-cache-wait-duration 1m --stream-metadata-cache-wait-duration 1m + healthcheck: + test: [ "CMD", "sh", "-c", "nc -nz 127.0.0.1 17912" ] interval: 5s timeout: 60s retries: 120 diff --git a/test/e2e/base/pom.xml b/test/e2e/base/pom.xml index 9ae8d9e70e..63b6a687f2 100644 --- a/test/e2e/base/pom.xml +++ b/test/e2e/base/pom.xml @@ -51,7 +51,7 @@ ${java.version} ${java.version} UTF-8 - 2.2.5.RELEASE + 2.7.18 30.1.1-jre 1.18.20 diff --git a/test/e2e/case/expected/event-list.yml b/test/e2e/case/expected/event-list.yml index e5a19bfe07..e020869abc 100644 --- a/test/e2e/case/expected/event-list.yml +++ b/test/e2e/case/expected/event-list.yml @@ -30,5 +30,5 @@ events: {{- end }} starttime: {{ gt .starttime 0 }} endtime: {{ gt .endtime 0 }} -{{- end }} -total: {{ gt .total 0 }} \ No newline at end of file + layer: "GENERAL" +{{- end }} \ No newline at end of file diff --git a/test/e2e/case/expected/logs-list.yml b/test/e2e/case/expected/logs-list.yml index 23de580d25..2e02cbd076 100644 --- a/test/e2e/case/expected/logs-list.yml +++ b/test/e2e/case/expected/logs-list.yml @@ -36,4 +36,5 @@ logs: value: {{ notEmpty .value }} {{- end }} {{- end }} -total: {{ gt .total 0 }} +debuggingtrace: null +errorreason: null \ No newline at end of file diff --git a/test/e2e/case/expected/metrics-has-value.yml b/test/e2e/case/expected/metrics-has-value.yml index 27ae47c8ff..baeae56d1c 100644 --- a/test/e2e/case/expected/metrics-has-value.yml +++ b/test/e2e/case/expected/metrics-has-value.yml @@ -13,9 +13,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -{{- contains . }} + {{- contains . }} - key: {{ notEmpty .key }} - value: {{ ge .value 0 }} + value: + value: 0 + isemptyvalue: true - key: {{ notEmpty .key }} - value: {{ ge .value 1 }} -{{- end }} \ No newline at end of file + value: + value: {{ ge .value.value 1 }} + isemptyvalue: false + {{- end }} \ No newline at end of file diff --git a/test/e2e/case/expected/service.yml b/test/e2e/case/expected/service.yml index 129f9d3e8b..e60a3313db 100644 --- a/test/e2e/case/expected/service.yml +++ b/test/e2e/case/expected/service.yml @@ -13,9 +13,28 @@ # See the License for the specific language governing permissions and # limitations under the License. +{{- contains . }} - id: {{ b64enc "e2e-service-provider" }}.1 name: e2e-service-provider group: "" + shortname: e2e-service-provider + normal: true + layers: + - SO11Y_JAVA_AGENT + - GENERAL - id: {{ b64enc "e2e-service-consumer" }}.1 name: e2e-service-consumer - group: "" \ No newline at end of file + group: "" + shortname: e2e-service-consumer + normal: true + layers: + - SO11Y_JAVA_AGENT + - GENERAL +- id: {{ b64enc "localhost:-1" }}.0 + name: localhost:-1 + group: "" + shortname: localhost:-1 + normal: false + layers: + - VIRTUAL_DATABASE +{{- end }} \ No newline at end of file diff --git a/test/e2e/case/expected/trace-info-detail.yml b/test/e2e/case/expected/trace-info-detail.yml index f50b094f53..fad2fdbe70 100644 --- a/test/e2e/case/expected/trace-info-detail.yml +++ b/test/e2e/case/expected/trace-info-detail.yml @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +debuggingtrace: null spans: {{- contains .spans}} - traceid: {{ notEmpty .traceid }} @@ -46,4 +47,5 @@ spans: value: '200' {{- end }} logs: [] + attachedevents: [] {{- end }} diff --git a/test/e2e/case/expected/trace-users-detail.yml b/test/e2e/case/expected/trace-users-detail.yml index 3a1030eea6..ef0d1a39cf 100644 --- a/test/e2e/case/expected/trace-users-detail.yml +++ b/test/e2e/case/expected/trace-users-detail.yml @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +debuggingtrace: null spans: {{- contains .spans}} - traceid: {{ notEmpty .traceid }} @@ -40,4 +41,5 @@ spans: value: '200' {{- end }} logs: [] + attachedevents: [] {{- end }} diff --git a/test/e2e/case/expected/traces-list.yml b/test/e2e/case/expected/traces-list.yml index bed95518e2..8996767757 100644 --- a/test/e2e/case/expected/traces-list.yml +++ b/test/e2e/case/expected/traces-list.yml @@ -13,17 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. +debuggingtrace: null traces: {{- contains .traces }} - - segmentid: {{ notEmpty .segmentid }} - endpointnames: - {{- contains .endpointnames }} - - POST:/info - {{- end }} - duration: {{ ge .duration 0 }} - start: "{{ notEmpty .start}}" - iserror: false - traceids: - - {{ (index .traceids 0) }} +- segmentid: {{ notEmpty .segmentid }} + endpointnames: + - POST:/info + duration: {{ ge .duration 0 }} + start: "{{ notEmpty .start}}" + iserror: false + traceids: + - {{ index .traceids 0 }} {{- end }} -total: {{ gt .total 0 }} diff --git a/test/e2e/case/grpc/docker-compose.yml b/test/e2e/case/grpc/docker-compose.yml index 621587bd60..f79160cb8c 100644 --- a/test/e2e/case/grpc/docker-compose.yml +++ b/test/e2e/case/grpc/docker-compose.yml @@ -23,6 +23,13 @@ services: ports: - 12800 + banyandb: + extends: + file: ../../base/base-compose.yml + service: banyandb + ports: + - 17912 + provider: extends: file: ../../base/base-compose.yml diff --git a/test/e2e/case/kafka/docker-compose.yml b/test/e2e/case/kafka/docker-compose.yml index 3760fd44fb..40bb4ba346 100644 --- a/test/e2e/case/kafka/docker-compose.yml +++ b/test/e2e/case/kafka/docker-compose.yml @@ -89,6 +89,13 @@ services: broker-b: condition: service_healthy + banyandb: + extends: + file: ../../base/base-compose.yml + service: banyandb + ports: + - 17912 + kafkaprovider: extends: file: ../../base/base-compose.yml diff --git a/test/e2e/script/env b/test/e2e/script/env index e57ec37b21..01f311a60b 100644 --- a/test/e2e/script/env +++ b/test/e2e/script/env @@ -13,4 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -SW_CTL_COMMIT=b90255132f916f53eb90955cc8a6445b03a4bec3 +SW_CTL_COMMIT=77b4c49e89c9c000278f44e62729d534f2ec842e +SW_OAP_COMMIT=dc8740d4757b35374283c4850a9a080e40f0eb79 +SW_BANYANDB_COMMIT=7e5b2d0404e8ad6d5835eee6fe589a2544d0decb \ No newline at end of file diff --git a/test/e2e/script/prepare/install-swctl.sh b/test/e2e/script/prepare/install-swctl.sh index 587541f7ee..d435f5ad92 100644 --- a/test/e2e/script/prepare/install-swctl.sh +++ b/test/e2e/script/prepare/install-swctl.sh @@ -22,12 +22,18 @@ BASE_DIR=$1 BIN_DIR=$2 -set -ex - -if ! command -v swctl &> /dev/null; then +install_swctl() { mkdir -p $BASE_DIR/swctl && cd $BASE_DIR/swctl curl -kLo skywalking-cli.tar.gz https://github.com/apache/skywalking-cli/archive/${SW_CTL_COMMIT}.tar.gz tar -zxf skywalking-cli.tar.gz --strip=1 - utype=$(uname | awk '{print tolower($0)}') - make $utype && mv bin/swctl-*-$utype-amd64 $BIN_DIR/swctl -fi \ No newline at end of file + VERSION=${SW_CTL_COMMIT} make install DESTDIR=$BIN_DIR +} + +if ! command -v swctl &> /dev/null; then + echo "swctl is not installed" + install_swctl +elif ! swctl --version | grep -q "${SW_CTL_COMMIT::7}"; then + # Check if the installed version is correct + echo "swctl is already installed, but version is not ${SW_CTL_COMMIT}, will re-install it" + install_swctl +fi From 80d3958257962f00b0fff852561aef597f4683a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Thu, 21 Aug 2025 22:18:33 +0800 Subject: [PATCH 075/114] Bump up apache parent pom to v35. (#771) * Bump up apache parent pom to v35. * Update Maven to 3.6.3 in mvnw. Refer to Maven doc, > Starting with JDK 9, the javac executable can accept the --release option to specify against which Java SE release you want to build the project. For example, you have JDK 11 installed and used by Maven, but you want to build the project against Java 8. The --release option ensures that the code is compiled following the rules of the programming language of the specified release, and that generated classes target the release **as well as the public API of that release**. This means that, unlike the old [-source and -target options](https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html), the compiler will detect and generate an error when using APIs that don't exist in previous releases of Java SE. - https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-release.html --- .mvn/wrapper/maven-wrapper.properties | 2 +- CHANGES.md | 2 ++ .../elasticsearch-5.x-plugin/pom.xml | 3 --- .../apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml | 2 -- .../bootstrap-plugins/jdk-http-plugin/pom.xml | 2 ++ pom.xml | 5 ++++- test/plugin/pom.xml | 14 +++++++++++++- .../scenarios/micronaut-http-scenario/pom.xml | 8 +------- 8 files changed, 23 insertions(+), 15 deletions(-) diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 54ab0bc2f6..94a275913a 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,3 +1,3 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar diff --git a/CHANGES.md b/CHANGES.md index 8140e6c5d7..1f517d22d3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,8 @@ Release Notes. * Bump up guava to v32.1.3. * Bump up oap to the 10.3-dev.latest(dc8740d4757b35374283c4850a9a080e40f0eb79) in e2e. * Bump up cli to the 0.15.0-dev.latest(77b4c49e89c9c000278f44e62729d534f2ec842e) in e2e. +* Bump up apache parent pom to v35. +* Update Maven to 3.6.3 in mvnw. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml index e2862daf57..224a41ee5e 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml @@ -32,9 +32,6 @@ UTF-8 - 1.8 - ${java.version} - ${java.version} 5.6.6 diff --git a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml index d65f65cbb6..790a4b46a4 100644 --- a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml @@ -35,8 +35,6 @@ UTF-8 6.34.0 2.11.12 - 1.8 - 1.8 diff --git a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml index e1970ec4da..8bfa622165 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml @@ -32,6 +32,8 @@ UTF-8 + + diff --git a/pom.xml b/pom.xml index abeaac8ced..77678e9b66 100755 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache apache - 21 + 35 @@ -78,6 +78,9 @@ UTF-8 + 8 + 8 + 8 8 6.18 4.12 diff --git a/test/plugin/pom.xml b/test/plugin/pom.xml index 0b3033000e..b42f4a69b7 100644 --- a/test/plugin/pom.xml +++ b/test/plugin/pom.xml @@ -34,6 +34,18 @@ containers + + + set-compiler-release + + [9,) + + + ${java.version} + + + + 8 ${java.version} @@ -47,7 +59,7 @@ 1.18.20 1.24 - 3.8.1 + 3.14.0 true diff --git a/test/plugin/scenarios/micronaut-http-scenario/pom.xml b/test/plugin/scenarios/micronaut-http-scenario/pom.xml index f9706e1da6..f04874ebeb 100644 --- a/test/plugin/scenarios/micronaut-http-scenario/pom.xml +++ b/test/plugin/scenarios/micronaut-http-scenario/pom.xml @@ -29,13 +29,7 @@ micronaut-scenario jar - 1.8 - - - 1.8 netty - 1.8 - 1.8 org.apache.skywalking.apm.testcase.micronaut.Application @@ -134,7 +128,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.10.1 + 3.14.0 From d1af3f643d0cb17303dd4f6d6382a1fd6e9c2c32 Mon Sep 17 00:00:00 2001 From: hxd123456 <46563086+hxd123456@users.noreply.github.com> Date: Sat, 6 Sep 2025 12:04:28 +0800 Subject: [PATCH 076/114] Add limitation for the number of span logs, to avoid OOM (#773) --- CHANGES.md | 1 + .../org/apache/skywalking/apm/agent/core/conf/Config.java | 5 +++++ .../apm/agent/core/context/trace/AbstractTracingSpan.java | 6 ++++++ apm-sniffer/config/agent.config | 3 +++ 4 files changed, 15 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 1f517d22d3..f28bb6123e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ Release Notes. * Bump up cli to the 0.15.0-dev.latest(77b4c49e89c9c000278f44e62729d534f2ec842e) in e2e. * Bump up apache parent pom to v35. * Update Maven to 3.6.3 in mvnw. +* Fix OOM due to too many span logs. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java index 373ff40a0d..87cf57955b 100755 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/conf/Config.java @@ -97,6 +97,11 @@ public static class Agent { */ public static int TRACE_SEGMENT_REF_LIMIT_PER_SPAN = 500; + /** + * The max number of logs in a single span to keep memory cost estimatable. + */ + public static int LOG_LIMIT_PER_SPAN = 300; + /** * The max number of spans in a single segment. Through this config item, SkyWalking keep your application * memory cost estimated. diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java index 6c682ca412..a8ca96e07a 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/AbstractTracingSpan.java @@ -175,6 +175,9 @@ public AbstractTracingSpan log(Throwable t) { if (!errorOccurred && ServiceManager.INSTANCE.findService(StatusCheckService.class).isError(t)) { errorOccurred(); } + if (logs.size() >= Config.Agent.LOG_LIMIT_PER_SPAN) { + return this; + } logs.add(new LogDataEntity.Builder().add(new KeyValuePair("event", "error")) .add(new KeyValuePair("error.kind", t.getClass().getName())) .add(new KeyValuePair("message", t.getMessage())) @@ -196,6 +199,9 @@ public AbstractTracingSpan log(long timestampMicroseconds, Map fields if (logs == null) { logs = new LinkedList<>(); } + if (logs.size() >= Config.Agent.LOG_LIMIT_PER_SPAN) { + return this; + } LogDataEntity.Builder builder = new LogDataEntity.Builder(); for (Map.Entry entry : fields.entrySet()) { builder.add(new KeyValuePair(entry.getKey(), entry.getValue().toString())); diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index f27572a1e0..9056993626 100755 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -36,6 +36,9 @@ agent.authentication=${SW_AGENT_AUTHENTICATION:} # The max number of TraceSegmentRef in a single span to keep memory cost estimatable. agent.trace_segment_ref_limit_per_span=${SW_TRACE_SEGMENT_LIMIT:500} +# The max number of logs in a single span to keep memory cost estimatable. +agent.log_limit_per_span=${SW_LOG_LIMIT_PER_SPAN:500} + # The max amount of spans in a single segment. # Through this config item, SkyWalking keep your application memory cost estimated. agent.span_limit_per_segment=${SW_AGENT_SPAN_LIMIT:300} From 762d31fa0f462c3025adf6af2d862e52c37f6815 Mon Sep 17 00:00:00 2001 From: Gong Dewei Date: Mon, 15 Sep 2025 17:19:57 +0800 Subject: [PATCH 077/114] Fix CLASS_LOADER_TYPE_CACHE OOM issue with WeakHashMap (#772) --- CHANGES.md | 1 + .../agent/builder/SWDescriptionStrategy.java | 26 +- .../SWDescriptionStrategyCacheTest.java | 239 ++++++++++++++++++ 3 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 apm-sniffer/bytebuddy-patch/src/test/java/net/bytebuddy/agent/builder/SWDescriptionStrategyCacheTest.java diff --git a/CHANGES.md b/CHANGES.md index f28bb6123e..731f74226a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ Release Notes. * Bump up apache parent pom to v35. * Update Maven to 3.6.3 in mvnw. * Fix OOM due to too many span logs. +* Fix ClassLoader cache OOM issue with WeakHashMap. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/apm-sniffer/bytebuddy-patch/src/main/java/net/bytebuddy/agent/builder/SWDescriptionStrategy.java b/apm-sniffer/bytebuddy-patch/src/main/java/net/bytebuddy/agent/builder/SWDescriptionStrategy.java index 62e8a0606c..0d10a039bb 100644 --- a/apm-sniffer/bytebuddy-patch/src/main/java/net/bytebuddy/agent/builder/SWDescriptionStrategy.java +++ b/apm-sniffer/bytebuddy-patch/src/main/java/net/bytebuddy/agent/builder/SWDescriptionStrategy.java @@ -34,10 +34,12 @@ import java.io.Serializable; import java.lang.annotation.Annotation; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -125,9 +127,16 @@ static class SWTypeDescriptionWrapper extends TypeDescription.AbstractBase imple /** * Original type cache. - * classloader hashcode -> ( typeName -> type cache ) + * ClassLoader -> (typeName -> TypeCache) + * Using WeakHashMap to automatically clean up cache when ClassLoader is garbage collected. */ - private static final Map> CLASS_LOADER_TYPE_CACHE = new ConcurrentHashMap<>(); + private static final Map> CLASS_LOADER_TYPE_CACHE = + Collections.synchronizedMap(new WeakHashMap<>()); + + /** + * Bootstrap ClassLoader cache (null key cannot be stored in WeakHashMap) + */ + private static final Map BOOTSTRAP_TYPE_CACHE = new ConcurrentHashMap<>(); private static final List IGNORED_INTERFACES = Arrays.asList(EnhancedInstance.class.getName()); @@ -153,10 +162,15 @@ public SWTypeDescriptionWrapper(TypeDescription delegate, String nameTrait, Clas } private TypeCache getTypeCache() { - int classLoaderHashCode = classLoader != null ? classLoader.hashCode() : 0; - Map typeCacheMap = CLASS_LOADER_TYPE_CACHE.computeIfAbsent(classLoaderHashCode, k -> new ConcurrentHashMap<>()); - TypeCache typeCache = typeCacheMap.computeIfAbsent(typeName, k -> new TypeCache(typeName)); - return typeCache; + if (classLoader == null) { + // Bootstrap ClassLoader - use separate cache since null key cannot be stored in WeakHashMap + return BOOTSTRAP_TYPE_CACHE.computeIfAbsent(typeName, k -> new TypeCache(typeName)); + } else { + // Regular ClassLoader - use WeakHashMap for automatic cleanup + Map typeCacheMap = CLASS_LOADER_TYPE_CACHE.computeIfAbsent( + classLoader, k -> new ConcurrentHashMap<>()); + return typeCacheMap.computeIfAbsent(typeName, k -> new TypeCache(typeName)); + } } @Override diff --git a/apm-sniffer/bytebuddy-patch/src/test/java/net/bytebuddy/agent/builder/SWDescriptionStrategyCacheTest.java b/apm-sniffer/bytebuddy-patch/src/test/java/net/bytebuddy/agent/builder/SWDescriptionStrategyCacheTest.java new file mode 100644 index 0000000000..90f9e4a437 --- /dev/null +++ b/apm-sniffer/bytebuddy-patch/src/test/java/net/bytebuddy/agent/builder/SWDescriptionStrategyCacheTest.java @@ -0,0 +1,239 @@ +/* + * 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 net.bytebuddy.agent.builder; + +import org.junit.Test; +import org.junit.Assert; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URLClassLoader; +import java.net.URL; +import java.util.Map; + +/** + * Tests the behavior of the WeakHashMap caching mechanism in SWDescriptionStrategy. + */ +public class SWDescriptionStrategyCacheTest { + + @Test + public void testWeakHashMapCacheCleanup() throws Exception { + // Get static cache field + Field cacheField = SWDescriptionStrategy.SWTypeDescriptionWrapper.class + .getDeclaredField("CLASS_LOADER_TYPE_CACHE"); + cacheField.setAccessible(true); + @SuppressWarnings("unchecked") + Map> cache = + (Map>) cacheField.get(null); + + // Record initial cache size + int initialCacheSize = cache.size(); + + // Create test ClassLoader + URLClassLoader testClassLoader = new URLClassLoader(new URL[0], null); + String testTypeName = "com.test.DynamicClass"; + + // Create SWTypeDescriptionWrapper instance + SWDescriptionStrategy.SWTypeDescriptionWrapper wrapper = + new SWDescriptionStrategy.SWTypeDescriptionWrapper( + null, "test", testClassLoader, testTypeName); + + // Call getTypeCache method via reflection to trigger caching + Method getTypeCacheMethod = wrapper.getClass() + .getDeclaredMethod("getTypeCache"); + getTypeCacheMethod.setAccessible(true); + SWDescriptionStrategy.TypeCache typeCache = + (SWDescriptionStrategy.TypeCache) getTypeCacheMethod.invoke(wrapper); + + // Verify that the ClassLoader exists in cache + Assert.assertTrue("Cache should contain the test ClassLoader", + cache.containsKey(testClassLoader)); + Assert.assertNotNull("TypeCache should be created", typeCache); + Assert.assertEquals("Cache size should increase by 1", + initialCacheSize + 1, cache.size()); + + // Clear ClassLoader references, prepare for GC test + testClassLoader = null; + wrapper = null; + typeCache = null; + + // Force garbage collection + System.gc(); + Thread.sleep(100); + System.gc(); + Thread.sleep(100); + + // WeakHashMap should automatically clean up garbage collected ClassLoader entries + int attempts = 0; + int currentCacheSize = cache.size(); + while (currentCacheSize > initialCacheSize && attempts < 20) { + System.gc(); + Thread.sleep(50); + currentCacheSize = cache.size(); + attempts++; + } + + System.out.println("Cache size after GC: " + currentCacheSize + + " (initial: " + initialCacheSize + ", attempts: " + attempts + ")"); + + // Verify that WeakHashMap cleanup mechanism works properly + Assert.assertTrue("WeakHashMap should clean up entries or attempts should be reasonable", + currentCacheSize <= initialCacheSize + 1 && attempts < 20); + } + + @Test + public void testBootstrapClassLoaderHandling() throws Exception { + // Get Bootstrap ClassLoader cache field + Field bootstrapCacheField = SWDescriptionStrategy.SWTypeDescriptionWrapper.class + .getDeclaredField("BOOTSTRAP_TYPE_CACHE"); + bootstrapCacheField.setAccessible(true); + @SuppressWarnings("unchecked") + Map bootstrapCache = + (Map) bootstrapCacheField.get(null); + + int initialBootstrapCacheSize = bootstrapCache.size(); + + // Test Bootstrap ClassLoader (null) handling + String testTypeName = "test.BootstrapClass"; + SWDescriptionStrategy.SWTypeDescriptionWrapper wrapper = + new SWDescriptionStrategy.SWTypeDescriptionWrapper( + null, "test", null, testTypeName); + + // Call getTypeCache method via reflection + Method getTypeCacheMethod = wrapper.getClass() + .getDeclaredMethod("getTypeCache"); + getTypeCacheMethod.setAccessible(true); + SWDescriptionStrategy.TypeCache typeCache = + (SWDescriptionStrategy.TypeCache) getTypeCacheMethod.invoke(wrapper); + + // Verify Bootstrap ClassLoader cache handling + Assert.assertNotNull("TypeCache should be created for bootstrap classloader", typeCache); + Assert.assertTrue("Bootstrap cache should contain the type", + bootstrapCache.containsKey(testTypeName)); + Assert.assertEquals("Bootstrap cache size should increase by 1", + initialBootstrapCacheSize + 1, bootstrapCache.size()); + } + + @Test + public void testMultipleClassLoadersIndependentCache() throws Exception { + Field cacheField = SWDescriptionStrategy.SWTypeDescriptionWrapper.class + .getDeclaredField("CLASS_LOADER_TYPE_CACHE"); + cacheField.setAccessible(true); + @SuppressWarnings("unchecked") + Map> cache = + (Map>) cacheField.get(null); + + int initialCacheSize = cache.size(); + + // Create two different ClassLoaders + URLClassLoader classLoader1 = new URLClassLoader(new URL[0], null); + URLClassLoader classLoader2 = new URLClassLoader(new URL[0], null); + String testTypeName = "com.test.SameClassName"; + + // Create TypeCache with same class name for both ClassLoaders + SWDescriptionStrategy.SWTypeDescriptionWrapper wrapper1 = + new SWDescriptionStrategy.SWTypeDescriptionWrapper( + null, "test", classLoader1, testTypeName); + SWDescriptionStrategy.SWTypeDescriptionWrapper wrapper2 = + new SWDescriptionStrategy.SWTypeDescriptionWrapper( + null, "test", classLoader2, testTypeName); + + // Call getTypeCache method via reflection + Method getTypeCacheMethod = + SWDescriptionStrategy.SWTypeDescriptionWrapper.class.getDeclaredMethod("getTypeCache"); + getTypeCacheMethod.setAccessible(true); + + SWDescriptionStrategy.TypeCache typeCache1 = + (SWDescriptionStrategy.TypeCache) getTypeCacheMethod.invoke(wrapper1); + SWDescriptionStrategy.TypeCache typeCache2 = + (SWDescriptionStrategy.TypeCache) getTypeCacheMethod.invoke(wrapper2); + + // Verify that the two ClassLoaders have independent cache entries + Assert.assertNotNull("TypeCache1 should be created", typeCache1); + Assert.assertNotNull("TypeCache2 should be created", typeCache2); + Assert.assertNotSame("TypeCaches should be different instances", typeCache1, typeCache2); + + // Verify cache structure + Assert.assertEquals("Cache should contain both classloaders", + initialCacheSize + 2, cache.size()); + Assert.assertTrue("Cache should contain classloader1", cache.containsKey(classLoader1)); + Assert.assertTrue("Cache should contain classloader2", cache.containsKey(classLoader2)); + + // Verify each ClassLoader has independent type cache + Map typeCacheMap1 = cache.get(classLoader1); + Map typeCacheMap2 = cache.get(classLoader2); + + Assert.assertNotNull("ClassLoader1 should have type cache map", typeCacheMap1); + Assert.assertNotNull("ClassLoader2 should have type cache map", typeCacheMap2); + Assert.assertNotSame("Type cache maps should be different", typeCacheMap1, typeCacheMap2); + + Assert.assertTrue("ClassLoader1 cache should contain the type", + typeCacheMap1.containsKey(testTypeName)); + Assert.assertTrue("ClassLoader2 cache should contain the type", + typeCacheMap2.containsKey(testTypeName)); + } + + @Test + public void testConcurrentAccess() throws Exception { + // Test concurrent access scenario + final String testTypeName = "com.test.ConcurrentClass"; + final int threadCount = 10; + final Thread[] threads = new Thread[threadCount]; + final URLClassLoader[] classLoaders = new URLClassLoader[threadCount]; + final SWDescriptionStrategy.TypeCache[] results = new SWDescriptionStrategy.TypeCache[threadCount]; + + // Create multiple threads to access cache simultaneously + for (int i = 0; i < threadCount; i++) { + final int index = i; + classLoaders[i] = new URLClassLoader(new URL[0], null); + threads[i] = new Thread(() -> { + try { + SWDescriptionStrategy.SWTypeDescriptionWrapper wrapper = + new SWDescriptionStrategy.SWTypeDescriptionWrapper( + null, "test", classLoaders[index], testTypeName); + + Method getTypeCacheMethod = wrapper.getClass() + .getDeclaredMethod("getTypeCache"); + getTypeCacheMethod.setAccessible(true); + results[index] = (SWDescriptionStrategy.TypeCache) + getTypeCacheMethod.invoke(wrapper); + } catch (Exception e) { + Assert.fail("Concurrent access should not throw exception: " + e.getMessage()); + } + }); + } + + // Start all threads + for (Thread thread : threads) { + thread.start(); + } + + // Wait for all threads to complete + for (Thread thread : threads) { + thread.join(1000); // Wait at most 1 second + } + + // Verify all results + for (int i = 0; i < threadCount; i++) { + Assert.assertNotNull("Result " + i + " should not be null", results[i]); + } + + System.out.println("Concurrent access test completed successfully with " + threadCount + " threads"); + } +} \ No newline at end of file From bf2daf3e8bc4a3ec5ab0ceb6213cf57f563796ae Mon Sep 17 00:00:00 2001 From: xhrg <634789257@qq.com> Date: Fri, 26 Sep 2025 08:43:46 +0800 Subject: [PATCH 078/114] Fix Jetty client cannot receive the HTTP response body(#13500) (#775) --- CHANGES.md | 1 + .../AsyncHttpRequestSendInterceptor.java | 9 +- .../v90/client/CompleteListenerWrapper.java | 12 +-- .../v90/client/ResponseListenerWrapper.java | 85 +++++++++++++++++ .../define/HttpRequestInstrumentation.java | 4 +- .../ResponseNotifierInstrumentation.java | 4 +- .../jetty-client-9.x-plugin/pom.xml | 2 +- .../AsyncHttpRequestSendInterceptor.java | 9 +- .../v9/client/CompleteListenerWrapper.java | 12 +-- .../v9/client/ResponseListenerWrapper.java | 92 +++++++++++++++++++ .../AsyncHttpRequestSendInterceptorTest.java | 13 +-- .../SyncHttpRequestSendInterceptorTest.java | 7 +- .../controller/CaseController.java | 24 +++-- .../jettyserver/servlet/AsyncCaseServlet.java | 4 + .../jettyserver/servlet/CaseServlet.java | 4 + 15 files changed, 244 insertions(+), 38 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/ResponseListenerWrapper.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/ResponseListenerWrapper.java diff --git a/CHANGES.md b/CHANGES.md index 731f74226a..7d9f030558 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,7 @@ Release Notes. * Update Maven to 3.6.3 in mvnw. * Fix OOM due to too many span logs. * Fix ClassLoader cache OOM issue with WeakHashMap. +* Fix Jetty client cannot receive the HTTP response body. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/AsyncHttpRequestSendInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/AsyncHttpRequestSendInterceptor.java index 669b43ffda..2858afce44 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/AsyncHttpRequestSendInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/AsyncHttpRequestSendInterceptor.java @@ -58,8 +58,13 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr span.prepareForAsync(); request.attribute(Constants.SW_JETTY_EXIT_SPAN_KEY, span); - Response.CompleteListener callback = (Response.CompleteListener) allArguments[0]; - allArguments[0] = new CompleteListenerWrapper(callback, ContextManager.capture()); + if (allArguments[0] instanceof Response.Listener) { + Response.Listener listener = (Response.Listener) allArguments[0]; + allArguments[0] = new ResponseListenerWrapper(listener, ContextManager.capture()); + } else { + Response.CompleteListener listener = (Response.CompleteListener) allArguments[0]; + allArguments[0] = new CompleteListenerWrapper(listener, ContextManager.capture()); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/CompleteListenerWrapper.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/CompleteListenerWrapper.java index 0318bd4c00..294b32fe7d 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/CompleteListenerWrapper.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/CompleteListenerWrapper.java @@ -27,11 +27,11 @@ import org.eclipse.jetty.client.api.Result; public class CompleteListenerWrapper implements Response.CompleteListener { - private Response.CompleteListener callback; + private Response.CompleteListener listener; private ContextSnapshot context; - public CompleteListenerWrapper(Response.CompleteListener callback, ContextSnapshot context) { - this.callback = callback; + public CompleteListenerWrapper(Response.CompleteListener listener, ContextSnapshot context) { + this.listener = listener; this.context = context; } @@ -43,9 +43,9 @@ public void onComplete(Result result) { if (context != null) { ContextManager.continued(context); } - if (callback != null) { - callback.onComplete(result); + if (listener != null) { + listener.onComplete(result); } ContextManager.stopSpan(); } -} +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/ResponseListenerWrapper.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/ResponseListenerWrapper.java new file mode 100644 index 0000000000..cf3e097dda --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/ResponseListenerWrapper.java @@ -0,0 +1,85 @@ +/* + * 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.jetty.v90.client; + +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.context.trace.SpanLayer; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.http.HttpField; +import java.nio.ByteBuffer; + +public class ResponseListenerWrapper implements Response.Listener { + + private final Response.Listener listener; + + private final ContextSnapshot context; + + public ResponseListenerWrapper(Response.Listener listener, ContextSnapshot context) { + this.listener = listener; + this.context = context; + } + + @Override + public void onComplete(Result result) { + AbstractSpan span = ContextManager.createLocalSpan(Constants.PLUGIN_NAME + "/CompleteListener/onComplete"); + span.setComponent(ComponentsDefine.JETTY_CLIENT); + SpanLayer.asHttp(span); + if (context != null) { + ContextManager.continued(context); + } + if (listener != null) { + listener.onComplete(result); + } + ContextManager.stopSpan(); + } + + @Override + public void onHeaders(Response response) { + listener.onHeaders(response); + } + + @Override + public void onContent(Response response, ByteBuffer content) { + listener.onContent(response, content); + } + + @Override + public void onBegin(Response response) { + listener.onBegin(response); + } + + @Override + public boolean onHeader(Response response, HttpField field) { + return listener.onHeader(response, field); + } + + @Override + public void onSuccess(Response response) { + listener.onSuccess(response); + } + + @Override + public void onFailure(Response response, Throwable failure) { + listener.onFailure(response, failure); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/define/HttpRequestInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/define/HttpRequestInstrumentation.java index ef8daf105a..2bee7ecdc1 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/define/HttpRequestInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/define/HttpRequestInstrumentation.java @@ -41,7 +41,7 @@ public class HttpRequestInstrumentation extends ClassInstanceMethodsEnhancePlugi private static final String ENHANCE_CLASS = "org.eclipse.jetty.client.HttpRequest"; private static final String ENHANCE_CLASS_NAME = "send"; public static final String SYNC_SEND_INTERCEPTOR = - "org.apache.skywalking.apm.plugin.jetty.v90.client.SyncHttpRequestSendV90Interceptor"; + "org.apache.skywalking.apm.plugin.jetty.v90.client.SyncHttpRequestSendInterceptor"; public static final String ASYNC_SEND_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jetty.v90.client.AsyncHttpRequestSendInterceptor"; @@ -85,7 +85,7 @@ public String getMethodsInterceptor() { @Override public boolean isOverrideArgs() { - return false; + return true; } } }; diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/define/ResponseNotifierInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/define/ResponseNotifierInstrumentation.java index c4f39c4147..5502c8dc78 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/define/ResponseNotifierInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v90/client/define/ResponseNotifierInstrumentation.java @@ -41,10 +41,10 @@ */ public class ResponseNotifierInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { - private static final String ENHANCE_CLASS = "org.eclipse.jetty.client.tar"; + private static final String ENHANCE_CLASS = "org.eclipse.jetty.client.ResponseNotifier"; private static final String ENHANCE_CLASS_NAME = "notifyComplete"; public static final String SYNC_SEND_INTERCEPTOR = - "org.apache.skywalking.apm.plugin.jetty.v9.client.ResponseNotifierInterceptor"; + "org.apache.skywalking.apm.plugin.jetty.v90.client.ResponseNotifierInterceptor"; @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml index 6b92929f8b..229c401f21 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml @@ -31,7 +31,7 @@ http://maven.apache.org - 9.1.0.v20131115 + 9.2.23.v20171218 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java index 6f8870af49..6f39452e0c 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptor.java @@ -57,8 +57,13 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr span.prepareForAsync(); request.attribute(Constants.SW_JETTY_EXIT_SPAN_KEY, span); - Response.CompleteListener callback = (Response.CompleteListener) allArguments[0]; - allArguments[0] = new CompleteListenerWrapper(callback, ContextManager.capture()); + if (allArguments[0] instanceof Response.Listener) { + Response.Listener listener = (Response.Listener) allArguments[0]; + allArguments[0] = new ResponseListenerWrapper(listener, ContextManager.capture()); + } else { + Response.CompleteListener listener = (Response.CompleteListener) allArguments[0]; + allArguments[0] = new CompleteListenerWrapper(listener, ContextManager.capture()); + } } @Override diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerWrapper.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerWrapper.java index 50697bf3e4..156e636884 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerWrapper.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/CompleteListenerWrapper.java @@ -27,11 +27,11 @@ import org.eclipse.jetty.client.api.Result; public class CompleteListenerWrapper implements Response.CompleteListener { - private Response.CompleteListener callback; + private Response.CompleteListener listener; private ContextSnapshot context; - public CompleteListenerWrapper(Response.CompleteListener callback, ContextSnapshot context) { - this.callback = callback; + public CompleteListenerWrapper(Response.CompleteListener listener, ContextSnapshot context) { + this.listener = listener; this.context = context; } @@ -43,9 +43,9 @@ public void onComplete(Result result) { if (context != null) { ContextManager.continued(context); } - if (callback != null) { - callback.onComplete(result); + if (listener != null) { + listener.onComplete(result); } ContextManager.stopSpan(); } -} +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/ResponseListenerWrapper.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/ResponseListenerWrapper.java new file mode 100644 index 0000000000..09102cdc43 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/client/ResponseListenerWrapper.java @@ -0,0 +1,92 @@ +/* + * 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.jetty.v9.client; + +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.context.trace.SpanLayer; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.util.Callback; + +import java.nio.ByteBuffer; + +public class ResponseListenerWrapper implements Response.Listener { + + private final Response.Listener listener; + + private final ContextSnapshot context; + + public ResponseListenerWrapper(Response.Listener listener, ContextSnapshot context) { + this.listener = listener; + this.context = context; + } + + @Override + public void onComplete(Result result) { + AbstractSpan span = ContextManager.createLocalSpan(Constants.PLUGIN_NAME + "/CompleteListener/onComplete"); + span.setComponent(ComponentsDefine.JETTY_CLIENT); + SpanLayer.asHttp(span); + if (context != null) { + ContextManager.continued(context); + } + if (listener != null) { + listener.onComplete(result); + } + ContextManager.stopSpan(); + } + + @Override + public void onHeaders(Response response) { + listener.onHeaders(response); + } + + @Override + public void onContent(Response response, ByteBuffer content, Callback callback) { + listener.onContent(response, content, callback); + } + + @Override + public void onContent(Response response, ByteBuffer content) { + listener.onContent(response, content); + } + + @Override + public void onBegin(Response response) { + listener.onBegin(response); + } + + @Override + public boolean onHeader(Response response, HttpField field) { + return listener.onHeader(response, field); + } + + @Override + public void onSuccess(Response response) { + listener.onSuccess(response); + } + + @Override + public void onFailure(Response response, Throwable failure) { + listener.onFailure(response, failure); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java index ae3dc47db1..fb044435da 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/AsyncHttpRequestSendInterceptorTest.java @@ -33,6 +33,7 @@ import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpConversation; import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.ResponseNotifier; import org.eclipse.jetty.client.api.Response; @@ -82,8 +83,8 @@ public class AsyncHttpRequestSendInterceptorTest { @Before public void setUp() throws Exception { - httpRequestEnhancedInstance = new MockHttpRequest(httpClient, uri); - responseNotifierEnhancedInstance = new MockResponseNotifier(httpClient); + httpRequestEnhancedInstance = new MockHttpRequest(httpClient, new HttpConversation(), uri); + responseNotifierEnhancedInstance = new MockResponseNotifier(); Result results = new Result(httpRequestEnhancedInstance, response); allArguments = new Object[]{(Response.CompleteListener) result -> { }, results}; @@ -146,8 +147,8 @@ private void assertJettySpan() { } private class MockHttpRequest extends HttpRequest implements EnhancedInstance { - public MockHttpRequest(HttpClient httpClient, URI uri) { - super(httpClient, uri); + public MockHttpRequest(HttpClient client, HttpConversation conversation, URI uri) { + super(httpClient, conversation, uri); } @Override @@ -172,8 +173,8 @@ public void setSkyWalkingDynamicField(Object value) { } private class MockResponseNotifier extends ResponseNotifier implements EnhancedInstance { - public MockResponseNotifier(HttpClient client) { - super(client); + public MockResponseNotifier() { + super(); } @Override diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java index e4a861fbc7..6f9d2ec489 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/client/SyncHttpRequestSendInterceptorTest.java @@ -34,6 +34,7 @@ import org.apache.skywalking.apm.agent.test.tools.SpanAssert; import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpConversation; import org.eclipse.jetty.client.HttpRequest; import org.junit.Assert; import org.junit.Before; @@ -67,7 +68,7 @@ public class SyncHttpRequestSendInterceptorTest { @Before public void setUp() throws Exception { - enhancedInstance = new MockHttpRequest(httpClient, uri); + enhancedInstance = new MockHttpRequest(httpClient, new HttpConversation(), uri); allArguments = new Object[] { "OperationKey", "OperationValue" @@ -123,8 +124,8 @@ public void testMethodsAroundError() throws Throwable { } private class MockHttpRequest extends HttpRequest implements EnhancedInstance { - public MockHttpRequest(HttpClient httpClient, URI uri) { - super(httpClient, uri); + public MockHttpRequest(HttpClient client, HttpConversation conversation, URI uri) { + super(httpClient, conversation, uri); } @Override diff --git a/test/plugin/scenarios/jetty-scenario/jettyclient-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyclient/controller/CaseController.java b/test/plugin/scenarios/jetty-scenario/jettyclient-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyclient/controller/CaseController.java index d45d8adfed..4e31db9383 100644 --- a/test/plugin/scenarios/jetty-scenario/jettyclient-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyclient/controller/CaseController.java +++ b/test/plugin/scenarios/jetty-scenario/jettyclient-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyclient/controller/CaseController.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.testcase.jettyclient.contr; +package org.apache.skywalking.apm.testcase.jettyclient.controller; import javax.annotation.PostConstruct; import java.io.IOException; @@ -26,6 +26,8 @@ import org.apache.http.impl.client.HttpClients; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.client.util.BufferingResponseListener; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Controller; @@ -51,13 +53,19 @@ public void init() throws Exception { @ResponseBody public String jettyClientScenario() throws Exception { client.newRequest("http://" + jettyServerHost + ":18080/jettyserver-case/case/receiveContext-0").send(); - Response.CompleteListener listener = result -> { - CloseableHttpClient httpclient = HttpClients.createDefault(); - HttpGet httpget = new HttpGet("http://" + jettyServerHost + ":18080/jettyserver-case/case/receiveContext-0"); - try { - httpclient.execute(httpget); - } catch (IOException e) { - throw new RuntimeException(e); + Response.Listener listener = new BufferingResponseListener() { + public void onComplete(Result result) { + byte[] bytes = this.getContent(); + if (bytes == null || bytes.length == 0) { + throw new RuntimeException("content cant be empty"); + } + CloseableHttpClient httpclient = HttpClients.createDefault(); + HttpGet httpget = new HttpGet("http://" + jettyServerHost + ":18080/jettyserver-case/case/receiveContext-0"); + try { + httpclient.execute(httpget); + } catch (IOException e) { + throw new RuntimeException(e); + } } }; client.newRequest("http://" + jettyServerHost + ":18080/jettyserver-case/case/receiveContext-1").send(listener); diff --git a/test/plugin/scenarios/jetty-scenario/jettyserver-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyserver/servlet/AsyncCaseServlet.java b/test/plugin/scenarios/jetty-scenario/jettyserver-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyserver/servlet/AsyncCaseServlet.java index 667fdafd16..4075fc0e34 100644 --- a/test/plugin/scenarios/jetty-scenario/jettyserver-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyserver/servlet/AsyncCaseServlet.java +++ b/test/plugin/scenarios/jetty-scenario/jettyserver-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyserver/servlet/AsyncCaseServlet.java @@ -19,6 +19,7 @@ package org.apache.skywalking.apm.testcase.jettyserver.servlet; import java.io.IOException; +import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -31,6 +32,9 @@ public class AsyncCaseServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { Thread.sleep(2000); + resp.setContentType("text/plain;charset=UTF-8"); + PrintWriter out = resp.getWriter(); + out.print("Success"); } catch (InterruptedException e) { } } diff --git a/test/plugin/scenarios/jetty-scenario/jettyserver-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyserver/servlet/CaseServlet.java b/test/plugin/scenarios/jetty-scenario/jettyserver-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyserver/servlet/CaseServlet.java index 9dfae15f64..22b6eeac90 100644 --- a/test/plugin/scenarios/jetty-scenario/jettyserver-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyserver/servlet/CaseServlet.java +++ b/test/plugin/scenarios/jetty-scenario/jettyserver-scenario/src/main/java/org/apache/skywalking/apm/testcase/jettyserver/servlet/CaseServlet.java @@ -19,6 +19,7 @@ package org.apache.skywalking.apm.testcase.jettyserver.servlet; import java.io.IOException; +import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -31,6 +32,9 @@ public class CaseServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { Thread.sleep(2000); + resp.setContentType("text/plain;charset=UTF-8"); + PrintWriter out = resp.getWriter(); + out.print("Success"); } catch (InterruptedException e) { } } From 606c563ea9e1a9728cda9d78ba399744ef0e7e7e Mon Sep 17 00:00:00 2001 From: jiangyunpeng Date: Sun, 28 Sep 2025 21:03:55 +0800 Subject: [PATCH 079/114] Eliminate repeated code with HttpServletRequestWrapper in mvc-annotation-commons. (#776) --- CHANGES.md | 1 + .../commons/HttpServletRequestWrapper.java | 37 ++++++ .../commons/HttpServletRequestWrappers.java | 112 ++++++++++++++++++ .../spring/mvc/commons/RequestUtil.java | 29 +++++ .../AbstractMethodInterceptor.java | 108 ++++++++--------- 5 files changed, 230 insertions(+), 57 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrapper.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrappers.java diff --git a/CHANGES.md b/CHANGES.md index 7d9f030558..bd24e54cd1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ Release Notes. * Fix OOM due to too many span logs. * Fix ClassLoader cache OOM issue with WeakHashMap. * Fix Jetty client cannot receive the HTTP response body. +* Eliminate repeated code with HttpServletRequestWrapper in mvc-annotation-commons. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrapper.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrapper.java new file mode 100644 index 0000000000..d258f7a5f2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrapper.java @@ -0,0 +1,37 @@ +/* + * 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.spring.mvc.commons; + +import java.util.Enumeration; +import java.util.Map; + +public interface HttpServletRequestWrapper { + + String getHeader(String name); + + String getMethod(); + + StringBuffer getRequestURL(); + + String getRemoteHost(); + + Map getParameterMap(); + + public Enumeration getHeaders(String name); +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrappers.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrappers.java new file mode 100644 index 0000000000..663ad53c31 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrappers.java @@ -0,0 +1,112 @@ +/* + * 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.spring.mvc.commons; + +import java.util.Enumeration; +import java.util.Map; + +public class HttpServletRequestWrappers { + + public static HttpServletRequestWrapper wrap(jakarta.servlet.http.HttpServletRequest request) { + return new JakartaHttpServletRequest(request); + } + + public static HttpServletRequestWrapper wrap(javax.servlet.http.HttpServletRequest request) { + return new JavaxHttpServletRequest(request); + } + + public static class JakartaHttpServletRequest implements HttpServletRequestWrapper { + + private jakarta.servlet.http.HttpServletRequest jakartaRequest; + + public JakartaHttpServletRequest(jakarta.servlet.http.HttpServletRequest jakartaRequest) { + this.jakartaRequest = jakartaRequest; + } + + @Override + public String getHeader(String name) { + return jakartaRequest.getHeader(name); + } + + @Override + public String getMethod() { + return jakartaRequest.getMethod(); + } + + @Override + public StringBuffer getRequestURL() { + return jakartaRequest.getRequestURL(); + } + + @Override + public String getRemoteHost() { + return jakartaRequest.getRemoteHost(); + } + + @Override + public Map getParameterMap() { + return jakartaRequest.getParameterMap(); + } + + @Override + public Enumeration getHeaders(String name) { + return jakartaRequest.getHeaders(name); + } + + } + + public static class JavaxHttpServletRequest implements HttpServletRequestWrapper { + private javax.servlet.http.HttpServletRequest javaxRequest; + + public JavaxHttpServletRequest(javax.servlet.http.HttpServletRequest javaxRequest) { + this.javaxRequest = javaxRequest; + } + + @Override + public String getHeader(String name) { + return javaxRequest.getHeader(name); + } + + @Override + public String getMethod() { + return javaxRequest.getMethod(); + } + + @Override + public StringBuffer getRequestURL() { + return javaxRequest.getRequestURL(); + } + + @Override + public String getRemoteHost() { + return javaxRequest.getRemoteHost(); + } + + @Override + public Map getParameterMap() { + return javaxRequest.getParameterMap(); + } + + @Override + public Enumeration getHeaders(String name) { + return javaxRequest.getHeaders(name); + } + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java index b278c8f9e2..f4f23b1c5b 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java @@ -52,6 +52,16 @@ public static void collectHttpParam(jakarta.servlet.http.HttpServletRequest requ } } + public static void collectHttpParam(HttpServletRequestWrapper request, AbstractSpan span) { + final Map parameterMap = request.getParameterMap(); + if (parameterMap != null && !parameterMap.isEmpty()) { + String tagValue = CollectionUtil.toString(parameterMap); + tagValue = SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? + StringUtil.cut(tagValue, SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue; + Tags.HTTP.PARAMS.set(span, tagValue); + } + } + public static void collectHttpParam(ServerHttpRequest request, AbstractSpan span) { Map parameterMap = new HashMap<>(request.getQueryParams().size()); request.getQueryParams().forEach((key, value) -> { @@ -65,6 +75,25 @@ public static void collectHttpParam(ServerHttpRequest request, AbstractSpan span } } + public static void collectHttpHeaders(HttpServletRequestWrapper request, AbstractSpan span) { + final List headersList = new ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size()); + SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream() + .filter( + headerName -> request.getHeaders(headerName) != null) + .forEach(headerName -> { + Enumeration headerValues = request.getHeaders( + headerName); + List valueList = Collections.list( + headerValues); + if (!CollectionUtil.isEmpty(valueList)) { + String headerValue = valueList.toString(); + headersList.add(headerName + "=" + headerValue); + } + }); + + collectHttpHeaders(headersList, span); + } + public static void collectHttpHeaders(HttpServletRequest request, AbstractSpan span) { final List headersList = new ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size()); SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream() diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java index df3aa7583f..ac51e60b93 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java @@ -18,6 +18,9 @@ package org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor; +import java.lang.reflect.Method; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.skywalking.apm.agent.core.context.CarrierItem; import org.apache.skywalking.apm.agent.core.context.ContextCarrier; import org.apache.skywalking.apm.agent.core.context.ContextManager; @@ -34,6 +37,8 @@ import org.apache.skywalking.apm.agent.core.util.MethodUtil; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.apache.skywalking.apm.plugin.spring.mvc.commons.EnhanceRequireObjectCache; +import org.apache.skywalking.apm.plugin.spring.mvc.commons.HttpServletRequestWrapper; +import org.apache.skywalking.apm.plugin.spring.mvc.commons.HttpServletRequestWrappers; import org.apache.skywalking.apm.plugin.spring.mvc.commons.RequestUtil; import org.apache.skywalking.apm.plugin.spring.mvc.commons.SpringMVCPluginConfig; import org.apache.skywalking.apm.plugin.spring.mvc.commons.exception.IllegalMethodStackDepthException; @@ -41,10 +46,6 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.lang.reflect.Method; - import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.CONTROLLER_METHOD_STACK_DEPTH; import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.FORWARD_REQUEST_FLAG; import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.REACTIVE_ASYNC_SPAN_IN_RUNTIME_CONTEXT; @@ -68,10 +69,11 @@ public abstract class AbstractMethodInterceptor implements InstanceMethodsAround static { IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist( - AbstractMethodInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); + AbstractMethodInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist( - AbstractMethodInterceptor.class.getClassLoader(), - JAKARTA_SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); + AbstractMethodInterceptor.class.getClassLoader(), + JAKARTA_SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD + ); try { Class.forName(SERVLET_RESPONSE_CLASS, true, AbstractMethodInterceptor.class.getClassLoader()); IN_SERVLET_CONTAINER = true; @@ -113,53 +115,15 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr if (IN_SERVLET_CONTAINER && IS_JAVAX && HttpServletRequest.class.isAssignableFrom(request.getClass())) { final HttpServletRequest httpServletRequest = (HttpServletRequest) request; - CarrierItem next = contextCarrier.items(); - while (next.hasNext()) { - next = next.next(); - next.setHeadValue(httpServletRequest.getHeader(next.getHeadKey())); - } - - String operationName = this.buildOperationName(method, httpServletRequest.getMethod(), - (EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField()); - AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier); - Tags.URL.set(span, httpServletRequest.getRequestURL().toString()); - Tags.HTTP.METHOD.set(span, httpServletRequest.getMethod()); - span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION); - SpanLayer.asHttp(span); + handleBeforeMethod( + objInst, method, HttpServletRequestWrappers.wrap(httpServletRequest), contextCarrier); - if (SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) { - RequestUtil.collectHttpParam(httpServletRequest, span); - } - - if (!CollectionUtil.isEmpty(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS)) { - RequestUtil.collectHttpHeaders(httpServletRequest, span); - } - } else if (IN_SERVLET_CONTAINER && IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom(request.getClass())) { + } else if (IN_SERVLET_CONTAINER && IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom( + request.getClass())) { final jakarta.servlet.http.HttpServletRequest httpServletRequest = (jakarta.servlet.http.HttpServletRequest) request; - CarrierItem next = contextCarrier.items(); - while (next.hasNext()) { - next = next.next(); - next.setHeadValue(httpServletRequest.getHeader(next.getHeadKey())); - } - - String operationName = - this.buildOperationName(method, httpServletRequest.getMethod(), - (EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField()); - AbstractSpan span = - ContextManager.createEntrySpan(operationName, contextCarrier); - Tags.URL.set(span, httpServletRequest.getRequestURL().toString()); - Tags.HTTP.METHOD.set(span, httpServletRequest.getMethod()); - span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION); - SpanLayer.asHttp(span); - - if (SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) { - RequestUtil.collectHttpParam(httpServletRequest, span); - } + handleBeforeMethod( + objInst, method, HttpServletRequestWrappers.wrap(httpServletRequest), contextCarrier); - if (!CollectionUtil - .isEmpty(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS)) { - RequestUtil.collectHttpHeaders(httpServletRequest, span); - } } else if (ServerHttpRequest.class.isAssignableFrom(request.getClass())) { final ServerHttpRequest serverHttpRequest = (ServerHttpRequest) request; CarrierItem next = contextCarrier.items(); @@ -168,8 +132,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr next.setHeadValue(serverHttpRequest.getHeaders().getFirst(next.getHeadKey())); } - String operationName = this.buildOperationName(method, serverHttpRequest.getMethod().name(), - (EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField()); + String operationName = this.buildOperationName( + method, serverHttpRequest.getMethod().name(), + (EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField() + ); AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier); Tags.URL.set(span, serverHttpRequest.getURI().toString()); Tags.HTTP.METHOD.set(span, serverHttpRequest.getMethod().name()); @@ -198,6 +164,31 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } } + private void handleBeforeMethod(EnhancedInstance objInst, Method method, + HttpServletRequestWrapper httpServletRequest, ContextCarrier contextCarrier) { + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + next.setHeadValue(httpServletRequest.getHeader(next.getHeadKey())); + } + + String operationName = this.buildOperationName( + method, httpServletRequest.getMethod(), (EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField()); + AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier); + Tags.URL.set(span, httpServletRequest.getRequestURL().toString()); + Tags.HTTP.METHOD.set(span, httpServletRequest.getMethod()); + span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION); + SpanLayer.asHttp(span); + + if (SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) { + RequestUtil.collectHttpParam(httpServletRequest, span); + } + + if (!CollectionUtil.isEmpty(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS)) { + RequestUtil.collectHttpHeaders(httpServletRequest, span); + } + } + @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { @@ -232,9 +223,11 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA Integer statusCode = null; - if (IS_SERVLET_GET_STATUS_METHOD_EXIST && HttpServletResponse.class.isAssignableFrom(response.getClass())) { + if (IS_SERVLET_GET_STATUS_METHOD_EXIST && HttpServletResponse.class.isAssignableFrom( + response.getClass())) { statusCode = ((HttpServletResponse) response).getStatus(); - } else if (IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST && jakarta.servlet.http.HttpServletResponse.class.isAssignableFrom(response.getClass())) { + } else if (IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST && jakarta.servlet.http.HttpServletResponse.class.isAssignableFrom( + response.getClass())) { statusCode = ((jakarta.servlet.http.HttpServletResponse) response).getStatus(); } else if (ServerHttpResponse.class.isAssignableFrom(response.getClass())) { if (IS_SERVLET_GET_STATUS_METHOD_EXIST || IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST) { @@ -263,7 +256,8 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA if (!SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS && span.isProfiling()) { if (IS_JAVAX && HttpServletRequest.class.isAssignableFrom(request.getClass())) { RequestUtil.collectHttpParam((HttpServletRequest) request, span); - } else if (IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom(request.getClass())) { + } else if (IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom( + request.getClass())) { RequestUtil.collectHttpParam((jakarta.servlet.http.HttpServletRequest) request, span); } else if (ServerHttpRequest.class.isAssignableFrom(request.getClass())) { RequestUtil.collectHttpParam((ServerHttpRequest) request, span); @@ -309,7 +303,7 @@ private String buildOperationName(Method method, String httpMethod, EnhanceRequi pathMappingCache.addPathMapping(method, requestURL); requestURL = pathMappingCache.findPathMapping(method); } - operationName = String.join(":", httpMethod, requestURL); + operationName = String.join(":", httpMethod, requestURL); } return operationName; From e43a80273310352ca480fb5487f767fa73119be9 Mon Sep 17 00:00:00 2001 From: peachisai <2581009893@qq.com> Date: Sun, 2 Nov 2025 23:18:09 +0800 Subject: [PATCH 080/114] Add the JDK 11+ httpclient plugin (#778) --- .github/workflows/plugins-jdk11-test.3.yaml | 1 + CHANGES.md | 1 + .../jdk-httpclient-plugin/pom.xml | 46 +++++++ .../HttpClientSendAsyncInterceptor.java | 123 +++++++++++++++++ .../apm/plugin/HttpClientSendInterceptor.java | 108 +++++++++++++++ .../plugin/HttpRequestHeadersInterceptor.java | 62 +++++++++ .../define/HttpClientInstrumentation.java | 109 +++++++++++++++ .../define/HttpRequestInstrumentation.java | 75 ++++++++++ .../src/main/resources/skywalking-plugin.def | 18 +++ apm-sniffer/bootstrap-plugins/pom.xml | 1 + ...NettyHttpRequestEncoderTracingHandler.java | 1 - .../java-agent/Bootstrap-plugins.md | 1 + .../service-agent/java-agent/Plugin-list.md | 1 + test/e2e/case/kafka/docker-compose.yml | 4 +- .../configuration.yml | 2 +- .../jdk-httpclient-scenario/bin/startup.sh | 21 +++ .../config/expectedData.yaml | 111 +++++++++++++++ .../jdk-httpclient-scenario/configuration.yml | 22 +++ .../scenarios/jdk-httpclient-scenario/pom.xml | 128 ++++++++++++++++++ .../src/main/assembly/assembly.xml | 41 ++++++ .../testcase/jdk/httpclient/Application.java | 30 ++++ .../httpclient/controller/CaseController.java | 71 ++++++++++ .../httpclient/controller/UserController.java | 45 ++++++ .../jdk/httpclient/dto/UserLoginDTO.java | 40 ++++++ .../src/main/resources/application.yaml | 21 +++ .../support-version.list | 17 +++ .../pom.xml | 8 -- .../configuration.yml | 6 +- .../kafka-scenario/configuration.yml | 2 +- .../configuration.yml | 2 +- .../configuration.yml | 2 +- .../configuration.yml | 2 +- 32 files changed, 1103 insertions(+), 19 deletions(-) create mode 100644 apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/pom.xml create mode 100644 apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpClientSendAsyncInterceptor.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpClientSendInterceptor.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpRequestHeadersInterceptor.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/HttpClientInstrumentation.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/HttpRequestInstrumentation.java create mode 100644 apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/resources/skywalking-plugin.def create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/configuration.yml create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/pom.xml create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/Application.java create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/UserController.java create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/dto/UserLoginDTO.java create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/jdk-httpclient-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk11-test.3.yaml b/.github/workflows/plugins-jdk11-test.3.yaml index a1f90fff14..0e1fe2f74b 100644 --- a/.github/workflows/plugins-jdk11-test.3.yaml +++ b/.github/workflows/plugins-jdk11-test.3.yaml @@ -55,6 +55,7 @@ jobs: matrix: case: - jdk11-forkjoinpool-scenario + - jdk-httpclient-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index bd24e54cd1..76d64c9840 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ Release Notes. * Fix ClassLoader cache OOM issue with WeakHashMap. * Fix Jetty client cannot receive the HTTP response body. * Eliminate repeated code with HttpServletRequestWrapper in mvc-annotation-commons. +* Add the jdk httpclient plugin. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/pom.xml new file mode 100644 index 0000000000..88a0f72a99 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/pom.xml @@ -0,0 +1,46 @@ + + + + + bootstrap-plugins + org.apache.skywalking + 9.6.0-SNAPSHOT + + 4.0.0 + + apm-jdk-httpclient-plugin + jar + + apm-jdk-httpclient-plugin + http://maven.apache.org + + + UTF-8 + 11 + + + + + + maven-deploy-plugin + + + + + \ No newline at end of file diff --git a/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpClientSendAsyncInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpClientSendAsyncInterceptor.java new file mode 100644 index 0000000000..0661c4705f --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpClientSendAsyncInterceptor.java @@ -0,0 +1,123 @@ +/* + * 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.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +public class HttpClientSendAsyncInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + HttpRequest request = (HttpRequest) allArguments[0]; + URI uri = request.uri(); + + ContextCarrier contextCarrier = new ContextCarrier(); + AbstractSpan span = ContextManager.createExitSpan(buildOperationName(request.method(), uri), contextCarrier, getPeer(uri)); + + if (request instanceof EnhancedInstance) { + ((EnhancedInstance) request).setSkyWalkingDynamicField(contextCarrier); + } + + span.setComponent(ComponentsDefine.JDK_HTTP); + Tags.HTTP.METHOD.set(span, request.method()); + Tags.URL.set(span, String.valueOf(uri)); + SpanLayer.asHttp(span); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + + if (ContextManager.isActive()) { + AbstractSpan span = ContextManager.activeSpan(); + span.prepareForAsync(); + + if (ret != null) { + CompletableFuture future = (CompletableFuture) ret; + ret = future.whenComplete((response, throwable) -> { + try { + if (throwable != null) { + span.errorOccurred(); + span.log(throwable); + return; + } + if (response instanceof HttpResponse) { + HttpResponse httpResponse = (HttpResponse) response; + int statusCode = httpResponse.statusCode(); + Tags.HTTP_RESPONSE_STATUS_CODE.set(span, statusCode); + if (statusCode >= 400) { + span.errorOccurred(); + } + } + } finally { + span.asyncFinish(); + } + }); + } else { + Map eventMap = new HashMap(); + eventMap.put("error", "No response"); + span.log(System.currentTimeMillis(), eventMap); + span.errorOccurred(); + } + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().log(t); + } + } + + private String buildOperationName(String method, URI uri) { + String path = uri.getPath(); + if (path == null || path.isEmpty()) { + path = "/"; + } + return method + ":" + path; + } + + private String getPeer(URI uri) { + String host = uri.getHost(); + int port = uri.getPort(); + + if (port == -1) { + port = "https".equalsIgnoreCase(uri.getScheme()) ? 443 : 80; + } + + return host + ":" + port; + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpClientSendInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpClientSendInterceptor.java new file mode 100644 index 0000000000..3a06f59ad9 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpClientSendInterceptor.java @@ -0,0 +1,108 @@ +/* + * 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.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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; +import java.net.URI; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.HashMap; +import java.util.Map; + +public class HttpClientSendInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + HttpRequest request = (HttpRequest) allArguments[0]; + URI uri = request.uri(); + + ContextCarrier contextCarrier = new ContextCarrier(); + AbstractSpan span = ContextManager.createExitSpan(buildOperationName(request.method(), uri), contextCarrier, getPeer(uri)); + + if (request instanceof EnhancedInstance) { + ((EnhancedInstance) request).setSkyWalkingDynamicField(contextCarrier); + } + + span.setComponent(ComponentsDefine.JDK_HTTP); + Tags.HTTP.METHOD.set(span, request.method()); + Tags.URL.set(span, String.valueOf(uri)); + SpanLayer.asHttp(span); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + + if (ContextManager.isActive()) { + AbstractSpan span = ContextManager.activeSpan(); + if (ret != null) { + HttpResponse response = (HttpResponse) ret; + int statusCode = response.statusCode(); + + Tags.HTTP_RESPONSE_STATUS_CODE.set(span, response.statusCode()); + if (statusCode >= 400) { + span.errorOccurred(); + } + } else { + Map eventMap = new HashMap(); + eventMap.put("error", "No response"); + span.log(System.currentTimeMillis(), eventMap); + span.errorOccurred(); + } + + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().log(t); + } + } + + private String buildOperationName(String method, URI uri) { + String path = uri.getPath(); + if (path == null || path.isEmpty()) { + path = "/"; + } + return method + ":" + path; + } + + private String getPeer(URI uri) { + String host = uri.getHost(); + int port = uri.getPort(); + + if (port == -1) { + port = "https".equalsIgnoreCase(uri.getScheme()) ? 443 : 80; + } + + return host + ":" + port; + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpRequestHeadersInterceptor.java b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpRequestHeadersInterceptor.java new file mode 100644 index 0000000000..a6dc76650f --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/HttpRequestHeadersInterceptor.java @@ -0,0 +1,62 @@ +/* + * 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.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +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; +import java.net.http.HttpHeaders; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class HttpRequestHeadersInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + + ContextCarrier contextCarrier = (ContextCarrier) objInst.getSkyWalkingDynamicField(); + HttpHeaders originalHeaders = (HttpHeaders) ret; + final Map> headerMap = new HashMap<>(originalHeaders.map()); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + headerMap.put(next.getHeadKey(), List.of(next.getHeadValue())); + } + + return HttpHeaders.of(headerMap, (k, v) -> true); + } + + @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-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/HttpClientInstrumentation.java b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/HttpClientInstrumentation.java new file mode 100644 index 0000000000..18f7cf298b --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/HttpClientInstrumentation.java @@ -0,0 +1,109 @@ +/* + * 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.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.IndirectMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.logical.LogicalMatchOperation; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +public class HttpClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_PARENT_CLASS = "java.net.http.HttpClient"; + + private static final String EXCLUDE_CLASS = "jdk.internal.net.http.HttpClientFacade"; + + private static final String INTERCEPT_SEND_METHOD = "send"; + + private static final String INTERCEPT_SEND_ASYNC_METHOD = "sendAsync"; + + private static final String INTERCEPT_SEND_HANDLE = "org.apache.skywalking.apm.plugin.HttpClientSendInterceptor"; + + private static final String INTERCEPT_SEND_ASYNC_HANDLE = "org.apache.skywalking.apm.plugin.HttpClientSendAsyncInterceptor"; + + @Override + public boolean isBootstrapInstrumentation() { + return true; + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + protected ClassMatch enhanceClass() { + IndirectMatch parentType = HierarchyMatch.byHierarchyMatch(ENHANCE_PARENT_CLASS); + IndirectMatch excludeClass = LogicalMatchOperation.not(MultiClassNameMatch.byMultiClassMatch(EXCLUDE_CLASS)); + return LogicalMatchOperation.and(parentType, excludeClass); + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named(INTERCEPT_SEND_METHOD) + .and(ElementMatchers.takesArgument(0, named("java.net.http.HttpRequest"))) + .and(ElementMatchers.takesArguments(2)); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_SEND_HANDLE; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named(INTERCEPT_SEND_ASYNC_METHOD) + .and(ElementMatchers.takesArgument(0, named("java.net.http.HttpRequest"))) + .and(ElementMatchers.takesArgument(1, named("java.net.http.HttpResponse$BodyHandler"))) + .and(ElementMatchers.takesArgument(2, named("java.net.http.HttpResponse$PushPromiseHandler"))) + .and(ElementMatchers.takesArguments(3)); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_SEND_ASYNC_HANDLE; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + }; + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/HttpRequestInstrumentation.java b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/HttpRequestInstrumentation.java new file mode 100644 index 0000000000..18d47b6923 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/define/HttpRequestInstrumentation.java @@ -0,0 +1,75 @@ +/* + * 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.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class HttpRequestInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "jdk.internal.net.http.ImmutableHttpRequest"; + + private static final String INTERCEPT_HEADERS_METHOD = "headers"; + + private static final String INTERCEPT_HEADERS_HANDLE = "org.apache.skywalking.apm.plugin.HttpRequestHeadersInterceptor"; + + @Override + public boolean isBootstrapInstrumentation() { + return true; + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers.named(INTERCEPT_HEADERS_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_HEADERS_HANDLE; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..e4d1ef2562 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,18 @@ +# 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-httpclient-plugin=org.apache.skywalking.apm.plugin.define.HttpClientInstrumentation +jdk-httpclient-plugin=org.apache.skywalking.apm.plugin.define.HttpRequestInstrumentation \ No newline at end of file diff --git a/apm-sniffer/bootstrap-plugins/pom.xml b/apm-sniffer/bootstrap-plugins/pom.xml index 8d1424343c..cf1285cc07 100644 --- a/apm-sniffer/bootstrap-plugins/pom.xml +++ b/apm-sniffer/bootstrap-plugins/pom.xml @@ -44,6 +44,7 @@ jdk-threadpool-plugin jdk-forkjoinpool-plugin jdk-virtual-thread-executor-plugin + jdk-httpclient-plugin diff --git a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/http/handler/NettyHttpRequestEncoderTracingHandler.java b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/http/handler/NettyHttpRequestEncoderTracingHandler.java index bb34adbaac..38c8518fb3 100644 --- a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/http/handler/NettyHttpRequestEncoderTracingHandler.java +++ b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/netty/http/handler/NettyHttpRequestEncoderTracingHandler.java @@ -80,7 +80,6 @@ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress(); String peer = address.getHostString() + ":" + address.getPort(); String url = peer + uri; - String method = request.method().toString(); ContextCarrier contextCarrier = new ContextCarrier(); AbstractSpan span = ContextManager.createExitSpan(NettyConstants.NETTY_HTTP_OPERATION_PREFIX + uri, contextCarrier, peer); 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 7eec71899a..f03a4e21a7 100644 --- a/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md +++ b/docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md @@ -8,6 +8,7 @@ Now, we have the following known bootstrap plugins. * Plugin of JDK ThreadPoolExecutor. Agent is compatible with JDK 1.8+ * Plugin of JDK ForkJoinPool. Agent is compatible with JDK 1.8+ * Plugin of JDK VirtualThreadExecutor. Agent is compatible with JDK 21+ +* Plugin of JDK HttpClient. Agent is compatible with JDK 11+ ### HttpURLConnection Plugin Notice The plugin of JDK HttpURLConnection depended on `sun.net.*`. When using Java 9+, You should add some JVM options as follows: 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 58a3a50ffc..7d8933e5d3 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -47,6 +47,7 @@ - influxdb-2.x - jackson-2.x - jdk-http-plugin +- jdk-httpclient-plugin - jdk-threading-plugin - jdk-virtual-thread-executor-plugin - jedis-2.x-3.x diff --git a/test/e2e/case/kafka/docker-compose.yml b/test/e2e/case/kafka/docker-compose.yml index 40bb4ba346..4f25a14cd6 100644 --- a/test/e2e/case/kafka/docker-compose.yml +++ b/test/e2e/case/kafka/docker-compose.yml @@ -32,7 +32,7 @@ services: retries: 120 broker-a: - image: bitnami/kafka:2.4.1 + image: bitnamilegacy/kafka:2.4.1 hostname: broker-a expose: - 9092 @@ -52,7 +52,7 @@ services: retries: 120 broker-b: - image: bitnami/kafka:2.4.1 + image: bitnamilegacy/kafka:2.4.1 hostname: broker-b expose: - 9092 diff --git a/test/plugin/scenarios/elasticsearch-transport-6.x-scenario/configuration.yml b/test/plugin/scenarios/elasticsearch-transport-6.x-scenario/configuration.yml index cafc4a0571..a268b52e4c 100644 --- a/test/plugin/scenarios/elasticsearch-transport-6.x-scenario/configuration.yml +++ b/test/plugin/scenarios/elasticsearch-transport-6.x-scenario/configuration.yml @@ -20,7 +20,7 @@ environment: - elasticsearch.server=elasticsearch-server-6.x:9200 dependencies: elasticsearch-server-6.x: - image: bitnami/elasticsearch:${CASE_SERVER_IMAGE_VERSION} + image: bitnamilegacy/elasticsearch:${CASE_SERVER_IMAGE_VERSION} hostname: elasticsearch-server-6.x removeOnExit: true expose: diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/bin/startup.sh b/test/plugin/scenarios/jdk-httpclient-scenario/bin/startup.sh new file mode 100644 index 0000000000..6c3e9e8b21 --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-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-httpclient-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/config/expectedData.yaml b/test/plugin/scenarios/jdk-httpclient-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..f009e03a46 --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-scenario/config/expectedData.yaml @@ -0,0 +1,111 @@ +# 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-httpclient-scenario + segmentSize: gt 0 + segments: + - segmentId: not null + spans: + - operationName: POST:/user/login + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: 'false' + tags: + - { key: url, value: not null } + - { key: http.method, value: POST } + - { key: http.status_code, value: '200' } + refs: + - { parentEndpoint: GET:/case/jdk-httpclient-scenario-case, networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: jdk-httpclient-scenario, traceId: not null } + - segmentId: not null + spans: + - operationName: POST:/user/asyncLogin + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 14 + isError: false + spanType: Entry + peer: '' + skipAnalysis: 'false' + tags: + - { key: url, value: not null } + - { key: http.method, value: POST } + - { key: http.status_code, value: '200' } + refs: + - { parentEndpoint: GET:/case/jdk-httpclient-scenario-case, networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: jdk-httpclient-scenario, traceId: not null } + + - segmentId: not null + spans: + - operationName: POST:/jdk-httpclient-scenario/user/login + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 66 + isError: false + spanType: Exit + peer: not null + skipAnalysis: 'false' + tags: + - { key: http.method, value: POST } + - { key: url, value: http://localhost:8080/jdk-httpclient-scenario/user/login } + - { key: http.status_code, value: '200' } + + - operationName: POST:/jdk-httpclient-scenario/user/asyncLogin + parentSpanId: 0 + spanId: 2 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 66 + isError: false + spanType: Exit + peer: not null + skipAnalysis: 'false' + tags: + - { key: http.method, value: POST } + - { key: url, value: http://localhost:8080/jdk-httpclient-scenario/user/asyncLogin } + - { key: http.status_code, value: '200' } + + - operationName: GET:/case/jdk-httpclient-scenario-case + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - { key: url, value: http://localhost:8080/jdk-httpclient-scenario/case/jdk-httpclient-scenario-case } + - { key: http.method, value: GET } + - { key: http.status_code, value: '200' } + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/configuration.yml b/test/plugin/scenarios/jdk-httpclient-scenario/configuration.yml new file mode 100644 index 0000000000..a5fe9c2cb1 --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-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/jdk-httpclient-scenario/case/jdk-httpclient-scenario-case +healthCheck: http://localhost:8080/jdk-httpclient-scenario/case/healthCheck +runningMode: with_bootstrap +withPlugins: apm-jdk-httpclient-plugin-*.jar +startScript: ./bin/startup.sh diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/pom.xml b/test/plugin/scenarios/jdk-httpclient-scenario/pom.xml new file mode 100644 index 0000000000..406bb8f57d --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-scenario/pom.xml @@ -0,0 +1,128 @@ + + + + 4.0.0 + + org.apache.skywalking + jdk-httpclient-scenario + 5.0.0 + + + UTF-8 + 11 + 3.8.1 + 2.7.15 + + + skywalking-jdk-httpclient-scenario + + + + org.springframework.boot + spring-boot-starter-web + 2.7.15 + + + + com.alibaba + fastjson + 1.2.83 + + + + + jdk-httpclient-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + false + + + + + org.apache.maven.plugins + maven-jar-plugin + + + empty-javadoc-jar + package + + jar + + + javadoc + ${basedir}/javadoc + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..3ab23573ab --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ./target/jdk-httpclient-scenario.jar + ./libs + 0775 + + + \ No newline at end of file diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/Application.java b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/Application.java new file mode 100644 index 0000000000..5147a224ee --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/Application.java @@ -0,0 +1,30 @@ +/* + * 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.httpclient; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java new file mode 100644 index 0000000000..25d4f4e6b9 --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java @@ -0,0 +1,71 @@ +/* + * 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.httpclient.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.concurrent.CompletableFuture; + +@RestController +@RequestMapping("/case") +public class CaseController { + + @GetMapping("/healthCheck") + public String healthCheck() { + return "Success"; + } + + @GetMapping("/jdk-httpclient-scenario-case") + public String testCase() throws InterruptedException, IOException { + HttpClient client = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(10)) + .build(); + + String json = "{\n" + + " \"username\": \"Alice\",\n" + + " \"password\": 21231231231\n" + + "}"; + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:8080/jdk-httpclient-scenario/user/login")) + .timeout(Duration.ofSeconds(10)) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(json)) + .build(); + + client.send(request, HttpResponse.BodyHandlers.ofString()); + + HttpRequest asyncRequest = HttpRequest.newBuilder() + .uri(URI.create("http://localhost:8080/jdk-httpclient-scenario/user/asyncLogin")) + .timeout(Duration.ofSeconds(10)) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(json)) + .build(); + CompletableFuture> future = client.sendAsync(asyncRequest, HttpResponse.BodyHandlers.ofString()); + future.join(); + return "success"; + } +} diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/UserController.java b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/UserController.java new file mode 100644 index 0000000000..a9665ffcb6 --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/UserController.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 test.apache.skywalking.apm.testcase.jdk.httpclient.controller; + +import com.alibaba.fastjson.JSONObject; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import test.apache.skywalking.apm.testcase.jdk.httpclient.dto.UserLoginDTO; + +@RestController +@RequestMapping("/user") +public class UserController { + @PostMapping("/login") + public JSONObject login(@RequestBody UserLoginDTO userLoginDTO) { + JSONObject resultJson = new JSONObject(); + resultJson.put("code", 200); + resultJson.put("message", "success"); + return resultJson; + } + + @PostMapping("/asyncLogin") + public JSONObject asyncLogin(@RequestBody UserLoginDTO userLoginDTO) { + JSONObject resultJson = new JSONObject(); + resultJson.put("code", 200); + resultJson.put("message", "success"); + return resultJson; + } +} diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/dto/UserLoginDTO.java b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/dto/UserLoginDTO.java new file mode 100644 index 0000000000..1226f82d2d --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/dto/UserLoginDTO.java @@ -0,0 +1,40 @@ +/* + * 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.httpclient.dto; + +public class UserLoginDTO { + private String username; + + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..2bed23f8ca --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-scenario/src/main/resources/application.yaml @@ -0,0 +1,21 @@ +# 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 + servlet: + context-path: /jdk-httpclient-scenario + diff --git a/test/plugin/scenarios/jdk-httpclient-scenario/support-version.list b/test/plugin/scenarios/jdk-httpclient-scenario/support-version.list new file mode 100644 index 0000000000..feef03cdea --- /dev/null +++ b/test/plugin/scenarios/jdk-httpclient-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 diff --git a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml index a9b9bb25f6..cc26ef8c91 100644 --- a/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml +++ b/test/plugin/scenarios/jdk-virtual-thread-executor-scenario/pom.xml @@ -90,14 +90,6 @@ - - org.apache.maven.plugins - maven-compiler-plugin - - 21 - 21 - - org.apache.maven.plugins maven-javadoc-plugin diff --git a/test/plugin/scenarios/jedis-2.x-3.x-cluster-scenario/configuration.yml b/test/plugin/scenarios/jedis-2.x-3.x-cluster-scenario/configuration.yml index e37ee9af2f..79a60472da 100644 --- a/test/plugin/scenarios/jedis-2.x-3.x-cluster-scenario/configuration.yml +++ b/test/plugin/scenarios/jedis-2.x-3.x-cluster-scenario/configuration.yml @@ -23,19 +23,19 @@ environment: - SW_PLUGIN_JEDIS_TRACE_REDIS_PARAMETERS=true dependencies: redis-server1: - image: bitnami/redis-cluster:7.0 + image: bitnamilegacy/redis-cluster:7.0 hostname: redis-server1 environment: - ALLOW_EMPTY_PASSWORD=true - REDIS_NODES=redis-server1 redis-server2 redis-server3 redis-server2: - image: bitnami/redis-cluster:7.0 + image: bitnamilegacy/redis-cluster:7.0 hostname: redis-server2 environment: - ALLOW_EMPTY_PASSWORD=true - REDIS_NODES=redis-server1 redis-server2 redis-server3 redis-server3: - image: bitnami/redis-cluster:7.0 + image: bitnamilegacy/redis-cluster:7.0 hostname: redis-server3 depends_on: - redis-server1 diff --git a/test/plugin/scenarios/kafka-scenario/configuration.yml b/test/plugin/scenarios/kafka-scenario/configuration.yml index 5a74c2ba42..7db52f161f 100644 --- a/test/plugin/scenarios/kafka-scenario/configuration.yml +++ b/test/plugin/scenarios/kafka-scenario/configuration.yml @@ -28,7 +28,7 @@ dependencies: image: zookeeper:3.4 hostname: zookeeper-server kafka-server: - image: bitnami/kafka:2.1.1 + image: bitnamilegacy/kafka:2.4.1 hostname: kafka-server environment: - KAFKA_ZOOKEEPER_CONNECT=zookeeper-server:2181 diff --git a/test/plugin/scenarios/spring-kafka-1.3.x-scenario/configuration.yml b/test/plugin/scenarios/spring-kafka-1.3.x-scenario/configuration.yml index f608847078..8d387e2d45 100644 --- a/test/plugin/scenarios/spring-kafka-1.3.x-scenario/configuration.yml +++ b/test/plugin/scenarios/spring-kafka-1.3.x-scenario/configuration.yml @@ -28,7 +28,7 @@ dependencies: image: zookeeper:3.4 hostname: zookeeper-server kafka-server: - image: bitnami/kafka:2.1.1 + image: bitnamilegacy/kafka:2.4.1 hostname: kafka-server environment: - KAFKA_ZOOKEEPER_CONNECT=zookeeper-server:2181 diff --git a/test/plugin/scenarios/spring-kafka-2.2.x-scenario/configuration.yml b/test/plugin/scenarios/spring-kafka-2.2.x-scenario/configuration.yml index c8b94d2bee..164b29135a 100644 --- a/test/plugin/scenarios/spring-kafka-2.2.x-scenario/configuration.yml +++ b/test/plugin/scenarios/spring-kafka-2.2.x-scenario/configuration.yml @@ -28,7 +28,7 @@ dependencies: image: zookeeper:3.4 hostname: zookeeper-server kafka-server: - image: bitnami/kafka:2.1.1 + image: bitnamilegacy/kafka:2.4.1 hostname: kafka-server environment: - KAFKA_ZOOKEEPER_CONNECT=zookeeper-server:2181 diff --git a/test/plugin/scenarios/spring-kafka-2.3.x-scenario/configuration.yml b/test/plugin/scenarios/spring-kafka-2.3.x-scenario/configuration.yml index 3d40a52355..295f967541 100644 --- a/test/plugin/scenarios/spring-kafka-2.3.x-scenario/configuration.yml +++ b/test/plugin/scenarios/spring-kafka-2.3.x-scenario/configuration.yml @@ -28,7 +28,7 @@ dependencies: image: zookeeper:3.4 hostname: zookeeper-server kafka-server: - image: bitnami/kafka:2.1.1 + image: bitnamilegacy/kafka:2.4.1 hostname: kafka-server environment: - KAFKA_ZOOKEEPER_CONNECT=zookeeper-server:2181 From 53a00a69372f79af1ab2e57e488ce57ddb0c610a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8F=8A=E7=8F=8A?= <51699833+huangguangshan@users.noreply.github.com> Date: Thu, 13 Nov 2025 13:43:49 +0800 Subject: [PATCH 081/114] Fix Gateway 2.0.x plugin not activated for spring-cloud-starter-gateway 2.0.0.RELEASE (#779) --- CHANGES.md | 2 +- .../v20x/define/AbstractGateway200EnhancePluginDefine.java | 2 +- .../v20x/define/AbstractGateway200EnhancePluginDefineV2.java | 2 +- .../v20x/define/DispatcherHandlerInstrumentation.java | 2 +- .../v20x/define/ServerWebExchangeInstrumentation.java | 2 +- .../gateway-2.0.x-scenario/gateway-projectA-scenario/pom.xml | 5 +++++ .../scenarios/gateway-2.0.x-scenario/support-version.list | 3 ++- 7 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 76d64c9840..113f769f2f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,7 +19,7 @@ Release Notes. * Fix Jetty client cannot receive the HTTP response body. * Eliminate repeated code with HttpServletRequestWrapper in mvc-annotation-commons. * Add the jdk httpclient plugin. - +* Fix Gateway 2.0.x plugin not activated for spring-cloud-starter-gateway 2.0.0.RELEASE. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) ------------------ diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/AbstractGateway200EnhancePluginDefine.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/AbstractGateway200EnhancePluginDefine.java index baeb619eca..e260b8813c 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/AbstractGateway200EnhancePluginDefine.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/AbstractGateway200EnhancePluginDefine.java @@ -24,7 +24,7 @@ public abstract class AbstractGateway200EnhancePluginDefine extends ClassInstanc @Override protected String[] witnessClasses() { return new String[] { - "org.springframework.cloud.gateway.config.GatewayAutoConfiguration$1" + "org.springframework.cloud.gateway.config.GatewayAutoConfiguration" }; } } diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/AbstractGateway200EnhancePluginDefineV2.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/AbstractGateway200EnhancePluginDefineV2.java index 1f07c0ba89..c42e2df60d 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/AbstractGateway200EnhancePluginDefineV2.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/AbstractGateway200EnhancePluginDefineV2.java @@ -24,7 +24,7 @@ public abstract class AbstractGateway200EnhancePluginDefineV2 extends ClassInsta @Override protected String[] witnessClasses() { return new String[] { - "org.springframework.cloud.gateway.config.GatewayAutoConfiguration$1" + "org.springframework.cloud.gateway.config.GatewayAutoConfiguration" }; } } diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/DispatcherHandlerInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/DispatcherHandlerInstrumentation.java index be9f8668ab..1188ae1804 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/DispatcherHandlerInstrumentation.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/DispatcherHandlerInstrumentation.java @@ -23,7 +23,7 @@ public class DispatcherHandlerInstrumentation extends org.apache.skywalking.apm. @Override protected String[] witnessClasses() { return new String[] { - "org.springframework.cloud.gateway.config.GatewayAutoConfiguration$1" + "org.springframework.cloud.gateway.config.GatewayAutoConfiguration" }; } } diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/ServerWebExchangeInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/ServerWebExchangeInstrumentation.java index 029172d69d..bb2af27b54 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/ServerWebExchangeInstrumentation.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v20x/define/ServerWebExchangeInstrumentation.java @@ -23,7 +23,7 @@ public class ServerWebExchangeInstrumentation extends org.apache.skywalking.apm. @Override protected String[] witnessClasses() { return new String[] { - "org.springframework.cloud.gateway.config.GatewayAutoConfiguration$1" + "org.springframework.cloud.gateway.config.GatewayAutoConfiguration" }; } } diff --git a/test/plugin/scenarios/gateway-2.0.x-scenario/gateway-projectA-scenario/pom.xml b/test/plugin/scenarios/gateway-2.0.x-scenario/gateway-projectA-scenario/pom.xml index fc1fb5e6d6..446f5e9f28 100644 --- a/test/plugin/scenarios/gateway-2.0.x-scenario/gateway-projectA-scenario/pom.xml +++ b/test/plugin/scenarios/gateway-2.0.x-scenario/gateway-projectA-scenario/pom.xml @@ -34,6 +34,11 @@ spring-cloud-starter-gateway ${test.framework.version} + + io.projectreactor + reactor-core + 3.1.7.RELEASE + diff --git a/test/plugin/scenarios/gateway-2.0.x-scenario/support-version.list b/test/plugin/scenarios/gateway-2.0.x-scenario/support-version.list index 8e6ebcf1ab..bb0a110c46 100644 --- a/test/plugin/scenarios/gateway-2.0.x-scenario/support-version.list +++ b/test/plugin/scenarios/gateway-2.0.x-scenario/support-version.list @@ -14,4 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -2.0.4.RELEASE \ No newline at end of file +2.0.4.RELEASE +2.0.0.RELEASE \ No newline at end of file From 67ab8b222fbb9a71b450665eb9f733380d813b8a Mon Sep 17 00:00:00 2001 From: GuiSong <1217316870@qq.com> Date: Thu, 20 Nov 2025 23:22:39 +0800 Subject: [PATCH 082/114] Support kafka-clients-3.9.x intercept and Upgrade kafka-clients version in optional-reporter-plugins to 3.9.1 (#780) --- CHANGES.md | 3 ++ .../ClassicKafkaConsumerInstrumentation.java | 40 +++++++++++++++++++ .../src/main/resources/skywalking-plugin.def | 1 + apm-sniffer/optional-reporter-plugins/pom.xml | 2 +- .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 2 +- .../kafka-scenario/support-version.list | 1 + 7 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/ClassicKafkaConsumerInstrumentation.java diff --git a/CHANGES.md b/CHANGES.md index 113f769f2f..45b20f1aa8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,9 @@ Release Notes. * Eliminate repeated code with HttpServletRequestWrapper in mvc-annotation-commons. * Add the jdk httpclient plugin. * Fix Gateway 2.0.x plugin not activated for spring-cloud-starter-gateway 2.0.0.RELEASE. +* Support kafka-clients-3.9.x intercept. +* Upgrade kafka-clients version in optional-reporter-plugins to 3.9.1. + All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) ------------------ diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/ClassicKafkaConsumerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/ClassicKafkaConsumerInstrumentation.java new file mode 100644 index 0000000000..c2092c6de6 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/java/org/apache/skywalking/apm/plugin/kafka/define/ClassicKafkaConsumerInstrumentation.java @@ -0,0 +1,40 @@ +/* + * 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.kafka.define; + +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * For Kafka 3.9.x change + * + *

+ *  1. The class named LegacyKafkaConsumer was rename to ClassicKafkaConsumer
+ *  2. Because of the enhance class was changed, so we should create new Instrumentation to enhance the new class
+ * 
+ */ +public class ClassicKafkaConsumerInstrumentation extends KafkaConsumerInstrumentation { + private static final String ENHANCE_CLASS_39_CLASSIC = "org.apache.kafka.clients.consumer.internals.ClassicKafkaConsumer"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS_39_CLASSIC); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/resources/skywalking-plugin.def index a85deb260b..bb98b86a97 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/src/main/resources/skywalking-plugin.def @@ -21,3 +21,4 @@ kafka-0.11.x/1.x/2.x=org.apache.skywalking.apm.plugin.kafka.define.KafkaProducer kafka-0.11.x/1.x/2.x=org.apache.skywalking.apm.plugin.kafka.define.KafkaTemplateCallbackInstrumentation kafka-3.7.x=org.apache.skywalking.apm.plugin.kafka.define.Kafka37AsyncConsumerInstrumentation kafka-3.7.x=org.apache.skywalking.apm.plugin.kafka.define.Kafka37LegacyConsumerInstrumentation +kafka-3.9.x=org.apache.skywalking.apm.plugin.kafka.define.ClassicKafkaConsumerInstrumentation \ No newline at end of file diff --git a/apm-sniffer/optional-reporter-plugins/pom.xml b/apm-sniffer/optional-reporter-plugins/pom.xml index 32700b16af..260ddc308b 100644 --- a/apm-sniffer/optional-reporter-plugins/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/pom.xml @@ -41,7 +41,7 @@ 1.0b3 1.8.1 - 2.4.1 + 3.9.1 2.4.6.RELEASE
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 7d8933e5d3..c5a5bfd48f 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -57,6 +57,7 @@ - jetty-server-9.x - kafka-0.11.x/1.x/2.x - kafka-3.7.x +- kafka-3.9.x - kotlin-coroutine - lettuce-common - lettuce-5.x-6.4.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 23c5680cd3..63369af6ea 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -76,7 +76,7 @@ metrics based on the tracing data. * MQ * [RocketMQ](https://github.com/apache/rocketmq) 3.x-> 5.x * [RocketMQ-gRPC](http://github.com/apache/rocketmq-clients) 5.x - * [Kafka](http://kafka.apache.org) 0.11.0.0 -> 3.7.1 + * [Kafka](http://kafka.apache.org) 0.11.0.0 -> 3.9.1 * [Spring-Kafka](https://github.com/spring-projects/spring-kafka) Spring Kafka Consumer 1.3.x -> 2.3.x (2.0.x and 2.1.x not tested and not recommended by [the official document](https://spring.io/projects/spring-kafka)) * [ActiveMQ](https://github.com/apache/activemq) 5.10.0 -> 5.15.4 * [RabbitMQ](https://www.rabbitmq.com/) 3.x-> 5.x diff --git a/test/plugin/scenarios/kafka-scenario/support-version.list b/test/plugin/scenarios/kafka-scenario/support-version.list index 6e83b29a43..f59368c253 100644 --- a/test/plugin/scenarios/kafka-scenario/support-version.list +++ b/test/plugin/scenarios/kafka-scenario/support-version.list @@ -31,3 +31,4 @@ 3.6.0 3.7.0 3.7.1 +3.9.1 \ No newline at end of file From c30b98d91b9c93deb849709805ca8806f27e2f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E4=B8=96=E8=B6=85?= Date: Wed, 26 Nov 2025 19:55:19 +0800 Subject: [PATCH 083/114] Fix replaceParam when the replaced string contains a replacement marker (#782) --- CHANGES.md | 1 + .../core/logging/core/AbstractLogger.java | 16 +++--- .../core/logging/core/AbstractLoggerTest.java | 56 +++++++++++++++++++ 3 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLoggerTest.java diff --git a/CHANGES.md b/CHANGES.md index 45b20f1aa8..b27ad9805b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,6 +22,7 @@ Release Notes. * Fix Gateway 2.0.x plugin not activated for spring-cloud-starter-gateway 2.0.0.RELEASE. * Support kafka-clients-3.9.x intercept. * Upgrade kafka-clients version in optional-reporter-plugins to 3.9.1. +* Fix AbstractLogger replaceParam when the replaced string contains a replacement marker. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLogger.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLogger.java index 20b55589f9..4020359d0a 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLogger.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLogger.java @@ -32,7 +32,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.regex.Matcher; /** * An abstract class to simplify the real implementation of the loggers. @@ -189,18 +188,17 @@ protected String replaceParam(String message, Object... parameters) { int startSize = 0; int parametersIndex = 0; int index; - String tmpMessage = message; - while ((index = message.indexOf("{}", startSize)) != -1) { + StringBuilder sb = new StringBuilder(message); + while ((index = sb.indexOf("{}", startSize)) != -1) { if (parametersIndex >= parameters.length) { break; } - /** - * @Fix the Illegal group reference issue - */ - tmpMessage = tmpMessage.replaceFirst("\\{\\}", Matcher.quoteReplacement(String.valueOf(parameters[parametersIndex++]))); - startSize = index + 2; + + String replaced = String.valueOf(parameters[parametersIndex++]); + sb.replace(index, index + 2, replaced); + startSize = index + replaced.length(); } - return tmpMessage; + return sb.toString(); } protected void logger(LogLevel level, String message, Throwable e) { diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLoggerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLoggerTest.java new file mode 100644 index 0000000000..1d56d7700b --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/logging/core/AbstractLoggerTest.java @@ -0,0 +1,56 @@ +/* + * 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.agent.core.logging.core; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class AbstractLoggerTest { + + @Test + public void replaceParamNormal() { + TestLogger logger = new TestLogger("AbstractLoggerTest"); + String result = logger.testReplaceParam("from {} to {}", "a", "b"); + assertEquals("from a to b", result); + } + + @Test + public void replaceParamWithReplaceMark() { + TestLogger logger = new TestLogger("AbstractLoggerTest"); + String result = logger.testReplaceParam("from {} to {}", "a={}", "b={}"); + assertEquals("from a={} to b={}", result); + } + + private static class TestLogger extends AbstractLogger { + + public TestLogger(String targetClass) { + super(targetClass); + } + + @Override + protected String format(LogLevel level, String message, Throwable e) { + return message; + } + + String testReplaceParam(String message, Object... parameters) { + return replaceParam(message, parameters); + } + } +} \ No newline at end of file From 92292a504bcb07634e557e746fd582b5aa5c244f Mon Sep 17 00:00:00 2001 From: weixiang1862 <652048614@qq.com> Date: Thu, 11 Dec 2025 13:45:19 +0800 Subject: [PATCH 084/114] Fix `JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH` was not working in some plugins (#784) --- CHANGES.md | 1 + .../apm/plugin/jdbc/trace/CallableStatementTracing.java | 3 ++- .../apm/plugin/jdbc/trace/PreparedStatementTracing.java | 3 ++- .../skywalking/apm/plugin/jdbc/trace/StatementTracing.java | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b27ad9805b..1abe98d2d0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,7 @@ Release Notes. * Support kafka-clients-3.9.x intercept. * Upgrade kafka-clients version in optional-reporter-plugins to 3.9.1. * Fix AbstractLogger replaceParam when the replaced string contains a replacement marker. +* Fix `JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH` was not working in some plugins. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/CallableStatementTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/CallableStatementTracing.java index 58bea0fd22..2a3a1f33b0 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/CallableStatementTracing.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/CallableStatementTracing.java @@ -23,6 +23,7 @@ import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.plugin.jdbc.SqlBodyUtil; /** * {@link CallableStatementTracing} create an exit span when the client call the method in the class that extend {@link @@ -38,7 +39,7 @@ public static R execute(java.sql.CallableStatement realStatement, Connection Tags.DB_TYPE.set(span, connectInfo.getDBType()); SpanLayer.asDB(span); Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); - Tags.DB_STATEMENT.set(span, sql); + Tags.DB_STATEMENT.set(span, SqlBodyUtil.limitSqlBodySize(sql)); span.setComponent(connectInfo.getComponent()); return exec.exe(realStatement, sql); } catch (SQLException e) { diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/PreparedStatementTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/PreparedStatementTracing.java index 86989b7b3d..7c70cb65b0 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/PreparedStatementTracing.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/PreparedStatementTracing.java @@ -26,6 +26,7 @@ import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; import org.apache.skywalking.apm.plugin.jdbc.JDBCPluginConfig; import org.apache.skywalking.apm.plugin.jdbc.PreparedStatementParameterBuilder; +import org.apache.skywalking.apm.plugin.jdbc.SqlBodyUtil; import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos; /** @@ -42,7 +43,7 @@ public static R execute(java.sql.PreparedStatement realStatement, Connection try { Tags.DB_TYPE.set(span, connectInfo.getDBType()); Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); - Tags.DB_STATEMENT.set(span, sql); + Tags.DB_STATEMENT.set(span, SqlBodyUtil.limitSqlBodySize(sql)); span.setComponent(connectInfo.getComponent()); SpanLayer.asDB(span); if (JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS && Objects.nonNull(statementEnhanceInfos)) { diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/StatementTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/StatementTracing.java index c94b777441..cbac44a6fd 100644 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/StatementTracing.java +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/src/main/java/org/apache/skywalking/apm/plugin/jdbc/trace/StatementTracing.java @@ -23,6 +23,7 @@ import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.plugin.jdbc.SqlBodyUtil; /** * {@link PreparedStatementTracing} create an exit span when the client call the method in the class that extend {@link @@ -36,7 +37,7 @@ public static R execute(java.sql.Statement realStatement, ConnectionInfo con .getDatabasePeer()); Tags.DB_TYPE.set(span, connectInfo.getDBType()); Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); - Tags.DB_STATEMENT.set(span, sql); + Tags.DB_STATEMENT.set(span, SqlBodyUtil.limitSqlBodySize(sql)); span.setComponent(connectInfo.getComponent()); SpanLayer.asDB(span); return exec.exe(realStatement, sql); From aee6f46cbfb32ac489e738f9172848ba3a3c238f Mon Sep 17 00:00:00 2001 From: peachisai <2581009893@qq.com> Date: Sun, 14 Dec 2025 23:36:17 +0800 Subject: [PATCH 085/114] Add the JDK 25 support (#783) --- .../Dockerfile-tomcat-jdk25-withCurl | 21 ++++++ .github/workflows/ci.yaml | 2 + .github/workflows/plugins-jdk25-test.0.yaml | 74 +++++++++++++++++++ .github/workflows/publish-docker.yaml | 2 +- CHANGES.md | 3 + Makefile | 3 +- docs/en/contribution/compiling.md | 2 +- .../service-agent/java-agent/Plugin-test.md | 5 ++ .../setup/service-agent/java-agent/README.md | 2 +- pom.xml | 2 +- 10 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/Dockerfile-tomcat-jdk25-withCurl create mode 100644 .github/workflows/plugins-jdk25-test.0.yaml diff --git a/.github/workflows/Dockerfile-tomcat-jdk25-withCurl b/.github/workflows/Dockerfile-tomcat-jdk25-withCurl new file mode 100644 index 0000000000..dc510ffb4c --- /dev/null +++ b/.github/workflows/Dockerfile-tomcat-jdk25-withCurl @@ -0,0 +1,21 @@ +# 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. + +FROM tomcat:10.1.50-jdk25-temurin + +RUN apt-get update \ + && apt-get install -y --no-install-recommends curl \ + && rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b92e5370de..0bc7a9c0e9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -52,6 +52,8 @@ jobs: include: - os: ubuntu java-version: 21 + - os: ubuntu + java-version: 25 steps: - if: matrix.os == 'windows' name: Support longpaths diff --git a/.github/workflows/plugins-jdk25-test.0.yaml b/.github/workflows/plugins-jdk25-test.0.yaml new file mode 100644 index 0000000000..88c7213101 --- /dev/null +++ b/.github/workflows/plugins-jdk25-test.0.yaml @@ -0,0 +1,74 @@ +# 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. + +name: Test + +on: + pull_request: + paths: + - '.github/workflows/plugins-*.yaml' + - 'apm-application-toolkit/**' + - 'apm-commons/**' + - 'apm-protocol/**' + - 'apm-sniffer/**' + - 'test/plugin/**' + - '**/pom.xml' + - '!**.md' + +concurrency: + group: plugins-jdk25-1-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build: + name: Build + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - name: Build local tomcat-curl image + run: | + docker build -t tomcat-curl:10.1.50-jdk25-temurin \ + -f ./.github/workflows/Dockerfile-tomcat-jdk25-withCurl . + - name: Build + uses: ./.github/actions/build + with: + base_image_java: eclipse-temurin:25-jdk + base_image_tomcat: tomcat-curl:10.1.50-jdk25-temurin + + test: + needs: [ build ] + name: ${{ matrix.case }}-jdk25 + runs-on: ubuntu-latest + timeout-minutes: 90 + strategy: + matrix: + case: + - spring-6.x-scenario + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: actions/setup-java@v2 + with: + distribution: 'temurin' + java-version: '25' + - name: Run Test + uses: ./.github/actions/run + with: + test_case: ${{ matrix.case }} diff --git a/.github/workflows/publish-docker.yaml b/.github/workflows/publish-docker.yaml index 71597889a3..7c1f4726b5 100644 --- a/.github/workflows/publish-docker.yaml +++ b/.github/workflows/publish-docker.yaml @@ -64,7 +64,7 @@ jobs: timeout-minutes: 60 strategy: matrix: - java-version: [ 8, 11, 17, 21 ] + java-version: [ 8, 11, 17, 21, 25 ] env: TAG: ${{ github.sha }} steps: diff --git a/CHANGES.md b/CHANGES.md index 1abe98d2d0..ef7d4f8fba 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,6 +24,9 @@ Release Notes. * Upgrade kafka-clients version in optional-reporter-plugins to 3.9.1. * Fix AbstractLogger replaceParam when the replaced string contains a replacement marker. * Fix `JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH` was not working in some plugins. +* Bump up Lombok to v1.18.42 to adopt JDK25 compiling. +* Add `eclipse-temurin:25-jre` as another base image. +* Add JDK25 plugin tests for Spring 6. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/Makefile b/Makefile index b0b6adde5e..965c6572bc 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ dist: build # Docker build -base.all := alpine java8 java11 java17 java21 +base.all := alpine java8 java11 java17 java21 java25 base.each = $(word 1, $@) base.image.alpine := alpine:3 @@ -42,6 +42,7 @@ base.image.java8 := eclipse-temurin:8-jre base.image.java11 := eclipse-temurin:11-jre base.image.java17 := eclipse-temurin:17-jre base.image.java21 := eclipse-temurin:21-jre +base.image.java25 := eclipse-temurin:25-jre docker.%: PLATFORMS = docker.%: LOAD_OR_PUSH = --load diff --git a/docs/en/contribution/compiling.md b/docs/en/contribution/compiling.md index d1507cc47a..da69b48a91 100644 --- a/docs/en/contribution/compiling.md +++ b/docs/en/contribution/compiling.md @@ -1,7 +1,7 @@ # Compiling project This document will help you compile and build a project in your maven and set your IDE. -Prepare JDK 17 or 21. +Prepare JDK 17, 21 or 25. * If you clone codes from https://github.com/apache/skywalking-java ```shell diff --git a/docs/en/setup/service-agent/java-agent/Plugin-test.md b/docs/en/setup/service-agent/java-agent/Plugin-test.md index c91402e6c5..e9dabb7515 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-test.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-test.md @@ -38,6 +38,10 @@ The test case project must be packaged as `project-name.war` by using `mvn packa Take the following test project as an example * [spring-4.3.x-scenario](../../../../../test/plugin/scenarios/spring-4.3.x-scenario) +Note on `tomcat:10.1.50-jdk25-temurin` image: + +Starting from JDK 22, the Tomcat community removed `curl` from the official Tomcat JDK images. Since `curl` is required by our plugin test framework, we provide a custom `tomcat-jdk25` image built with `curl` installed. +You can refer to the [tomcat-jdk25-dockerFile](../../../../../.github/workflows/Dockerfile-tomcat-jdk25-withCurl) to build the image for local plugin tests. ## Test project hierarchical structure The test case is an independent maven project, and it must be packaged as a war tar ball or zip file, depending on the chosen base image. Also, two external accessible endpoints usually two URLs) are required. @@ -682,6 +686,7 @@ You can run `python3 tools/select-group.py` to see which file contains the least If a test case required to run in JDK 17 environment, please add you test case into file `plugins-jdk17-test..yaml`. If a test case required to run in JDK 21 environment, please add you test case into file `plugins-jdk21-test..yaml`. +If a test case required to run in JDK 25 environment, please add you test case into file `plugins-jdk25-test..yaml`. ```yaml jobs: diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md index f6702c006f..d829b741fc 100755 --- a/docs/en/setup/service-agent/java-agent/README.md +++ b/docs/en/setup/service-agent/java-agent/README.md @@ -1,6 +1,6 @@ # Setup java agent -1. Agent is available for JDK 8 - 21. +1. Agent is available for JDK 8 - 25. 1. Find `agent` folder in SkyWalking release package 1. Set `agent.service_name` in `config/agent.config`. Could be any String in English. 1. Set `collector.backend_service` in `config/agent.config`. Default point to `127.0.0.1:11800`, only works for local diff --git a/pom.xml b/pom.xml index 77678e9b66..8e85a9cee4 100755 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ 4.12 5.0.0 2.0.2 - 1.18.30 + 1.18.42 1.17.6 From 759c45ff758a4143783085cd1036c3f286aed4a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E4=B8=96=E8=B6=85?= Date: Fri, 26 Dec 2025 20:23:30 +0800 Subject: [PATCH 086/114] Ignore classes starting with "sun.nio.cs" in bytebuddy due to potential class loading deadlock (#785) --- CHANGES.md | 1 + .../java/org/apache/skywalking/apm/agent/SkyWalkingAgent.java | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index ef7d4f8fba..54f75eeb97 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -27,6 +27,7 @@ Release Notes. * Bump up Lombok to v1.18.42 to adopt JDK25 compiling. * Add `eclipse-temurin:25-jre` as another base image. * Add JDK25 plugin tests for Spring 6. +* Ignore classes starting with "sun.nio.cs" in bytebuddy due to potential class loading deadlock. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) 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 2dd3fe8b38..b0dc55913f 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 @@ -128,6 +128,7 @@ static void installClassTransformer(Instrumentation instrumentation, PluginFinde .or(nameContains(".asm.")) .or(nameContains(".reflectasm.")) .or(nameStartsWith("sun.reflect")) + .or(nameStartsWith("sun.nio.cs")) .or(allSkyWalkingAgentExcludeToolkit()) .or(ElementMatchers.isSynthetic())); From 2a61027e5eb74ed1258c764ae2ffeabd499416a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Tue, 20 Jan 2026 21:37:22 +0800 Subject: [PATCH 087/114] Add CLAUDE.md for AI assistant guidance (#786) Add a comprehensive guide for AI assistants working with the SkyWalking Java Agent codebase, including: - Project overview and repository structure - Build system and commands - Plugin development with V2 API (recommended) vs V1 API (legacy) - Plugin development rules and dependency management - Tracing concepts and meter APIs - Plugin test framework documentation - Code style and conventions - PR guidelines and templates --- CHANGES.md | 1 + CLAUDE.md | 697 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 698 insertions(+) create mode 100644 CLAUDE.md diff --git a/CHANGES.md b/CHANGES.md index 54f75eeb97..979502ce7a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ Release Notes. 9.6.0 ------------------ +* Add CLAUDE.md for AI assistant guidance. * Bump up agent-oap protocol to latest(16c51358ebcf42629bf4ffdf952253971f20eb25). * Bump up gRPC to v1.74.0. * Bump up netty to v4.1.124.Final. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000..90e3bf0f6c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,697 @@ +# CLAUDE.md - AI Assistant Guide for Apache SkyWalking Java Agent + +This file provides guidance for AI assistants working with the Apache SkyWalking Java Agent codebase. + +## Project Overview + +Apache SkyWalking Java Agent is a Java-based APM (Application Performance Monitoring) agent designed for microservices, cloud-native, and container-based architectures. It provides automatic instrumentation for distributed tracing, performance metrics collection, and context propagation across service boundaries using bytecode manipulation via ByteBuddy. + +## Repository Structure + +``` +skywalking-java/ +├── apm-commons/ # Shared utilities and libraries +│ ├── apm-datacarrier/ # Data buffering and transport +│ └── apm-util/ # Common utilities +├── apm-protocol/ # Protocol definitions +│ └── apm-network/ # gRPC protocol (submodule: skywalking-data-collect-protocol) +├── apm-sniffer/ # Core agent and plugins (MAIN MODULE) +│ ├── apm-agent/ # Main agent bootstrap and premain entry +│ ├── apm-agent-core/ # Core agent logic, instrumentation engine +│ ├── apm-sdk-plugin/ # Standard SDK plugins (70+ plugins) +│ ├── bootstrap-plugins/ # Bootstrap-level plugins (JDK-level) +│ ├── optional-plugins/ # Optional framework plugins +│ ├── optional-reporter-plugins/ # Reporter plugins (Kafka, etc.) +│ ├── apm-toolkit-activation/ # Toolkit activations +│ ├── apm-test-tools/ # Testing utilities +│ ├── bytebuddy-patch/ # ByteBuddy patches +│ └── config/ # Default agent configurations +├── apm-application-toolkit/ # Public API for applications +│ ├── apm-toolkit-trace/ # Tracing API +│ ├── apm-toolkit-log4j-1.x/ # Log4j 1.x integration +│ ├── apm-toolkit-log4j-2.x/ # Log4j 2.x integration +│ ├── apm-toolkit-logback-1.x/ # Logback integration +│ ├── apm-toolkit-meter/ # Meter API +│ └── apm-toolkit-opentracing/ # OpenTracing API +├── apm-checkstyle/ # Code style configuration +│ ├── checkStyle.xml # Checkstyle rules +│ └── importControl.xml # Import control rules +├── test/ # Testing infrastructure +│ ├── plugin/ # Plugin E2E tests +│ │ ├── scenarios/ # Test scenarios (100+ scenarios) +│ │ ├── agent-test-tools/ # Mock collector, test utilities +│ │ ├── runner-helper/ # Test runner +│ │ └── containers/ # Docker test containers +│ └── e2e/ # End-to-end tests +├── docs/ # Documentation +├── tools/ # Build and utility tools +├── skywalking-agent/ # Built agent distribution output +├── changes/ # Changelog +└── dist-material/ # Distribution materials +``` + +## Build System + +### Prerequisites +- JDK 8, 11, 17, 21, or 25 +- Maven 3.6+ +- Git (with submodule support) + +### Common Build Commands + +```bash +# Clone with submodules +git clone --recurse-submodules https://github.com/apache/skywalking-java.git + +# Or initialize submodules after clone +git submodule init && git submodule update + +# Full build with tests +./mvnw clean install + +# Build without tests (recommended for development) +./mvnw clean package -Dmaven.test.skip=true + +# CI build with javadoc verification +./mvnw clean verify install javadoc:javadoc + +# Run checkstyle only +./mvnw checkstyle:check + +# Build with submodule update +./mvnw clean package -Pall + +# Docker build +make build +make docker +``` + +### Maven Profiles +- `all`: Includes git submodule update for protocol definitions + +### Key Build Properties +- ByteBuddy: 1.17.6 (bytecode manipulation) +- gRPC: 1.74.0 (communication protocol) +- Netty: 4.1.124.Final (network framework) +- Protobuf: 3.25.5 (protocol buffers) +- Lombok: 1.18.42 (annotation processing) + +## Architecture & Key Concepts + +### Agent Architecture +The agent uses ByteBuddy for bytecode manipulation at runtime: + +1. **Premain Entry**: `apm-agent/` contains the agent bootstrap via Java's `-javaagent` mechanism +2. **Instrumentation Engine**: `apm-agent-core/` handles class transformation and plugin loading +3. **Plugins**: Define which classes/methods to intercept and how to collect telemetry + +### Plugin Categories + +**1. SDK Plugins** (`apm-sniffer/apm-sdk-plugin/`) +- Framework-specific instrumentations (70+ plugins) +- Examples: grpc-1.x, spring, dubbo, mybatis, mongodb, redis, etc. +- Pattern: One directory per library/framework version + +**2. Bootstrap Plugins** (`apm-sniffer/bootstrap-plugins/`) +- Load at JVM bootstrap phase for JDK-level instrumentation +- Examples: jdk-threading, jdk-http, jdk-httpclient, jdk-virtual-thread-executor + +**3. Optional Plugins** (`apm-sniffer/optional-plugins/`) +- Not included by default, user must copy to plugins directory + +**4. Optional Reporter Plugins** (`apm-sniffer/optional-reporter-plugins/`) +- Alternative data collection backends (e.g., Kafka) + +### Plugin Instrumentation APIs (v1 vs v2) + +The agent provides two instrumentation APIs. **V2 is recommended** for all new plugins; v1 is legacy and should only be used for maintaining existing plugins. + +#### V2 API (Recommended) + +V2 provides a `MethodInvocationContext` that is shared across all interception phases (`beforeMethod`, `afterMethod`, `handleMethodException`), allowing you to pass data (e.g., spans) between phases. + +**Instrumentation class (extends `ClassEnhancePluginDefineV2`):** +```java +public class XxxInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 { + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName("target.class.Name"); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { ... }; + } + + @Override + public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { + return new InstanceMethodsInterceptV2Point[] { + new InstanceMethodsInterceptV2Point() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("targetMethod"); + } + + @Override + public String getMethodsInterceptorV2() { + return "org.apache.skywalking.apm.plugin.xxx.XxxInterceptor"; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} +``` + +**Interceptor class (implements `InstanceMethodsAroundInterceptorV2`):** +```java +public class XxxInterceptor implements InstanceMethodsAroundInterceptorV2 { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInvocationContext context) { + // Create span and store in context for later use + AbstractSpan span = ContextManager.createLocalSpan("operationName"); + context.setContext(span); // Pass to afterMethod/handleMethodException + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret, MethodInvocationContext context) { + // Retrieve span from context + AbstractSpan span = (AbstractSpan) context.getContext(); + span.asyncFinish(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { + AbstractSpan span = (AbstractSpan) context.getContext(); + span.log(t); + } +} +``` + +**Key V2 classes:** +- `ClassEnhancePluginDefineV2` - Base class for plugins with both instance and static methods +- `ClassInstanceMethodsEnhancePluginDefineV2` - For instance methods only +- `ClassStaticMethodsEnhancePluginDefineV2` - For static methods only +- `InstanceMethodsAroundInterceptorV2` - Interceptor interface with `MethodInvocationContext` +- `StaticMethodsAroundInterceptorV2` - Static method interceptor with context + +#### V1 API (Legacy) + +V1 uses `MethodInterceptResult` only in `beforeMethod` and has no shared context between phases. **Only use for maintaining existing legacy plugins.** + +**Key V1 classes (legacy):** +- `ClassEnhancePluginDefine` +- `ClassInstanceMethodsEnhancePluginDefine` +- `ClassStaticMethodsEnhancePluginDefine` +- `InstanceMethodsAroundInterceptor` +- `StaticMethodsAroundInterceptor` + +### Plugin Development Rules + +#### Class Matching Restrictions + +**CRITICAL: Never use `.class` references in instrumentation definitions:** +```java +// WRONG - will break the agent if ThirdPartyClass doesn't exist +takesArguments(ThirdPartyClass.class) +byName(ThirdPartyClass.class.getName()) + +// CORRECT - use string literals +takesArguments("com.example.ThirdPartyClass") +byName("com.example.ThirdPartyClass") +``` + +**ClassMatch options:** +- `byName(String)`: Match by full class name (package + class name) - **preferred** +- `byClassAnnotationMatch`: Match classes with specific annotations (does NOT support inherited annotations) +- `byMethodAnnotationMatch`: Match classes with methods having specific annotations +- `byHierarchyMatch`: Match by parent class/interface - **avoid unless necessary** (performance impact) + +#### Witness Classes/Methods + +Use witness classes/methods to activate plugins only for specific library versions: +```java +@Override +protected String[] witnessClasses() { + return new String[] { "com.example.VersionSpecificClass" }; +} + +@Override +protected List witnessMethods() { + return Collections.singletonList( + new WitnessMethod("com.example.SomeClass", ElementMatchers.named("specificMethod")) + ); +} +``` + +#### Bootstrap Instrumentation + +For JDK core classes (rt.jar), override `isBootstrapInstrumentation()`: +```java +@Override +public boolean isBootstrapInstrumentation() { + return true; +} +``` +**WARNING**: Use bootstrap instrumentation only where absolutely necessary. + +#### Plugin Configuration + +Use `@PluginConfig` annotation for custom plugin settings: +```java +public class MyPluginConfig { + public static class Plugin { + @PluginConfig(root = MyPluginConfig.class) + public static class MyPlugin { + public static boolean SOME_SETTING = false; + } + } +} +``` +Config key becomes: `plugin.myplugin.some_setting` + +#### Dependency Management + +**Plugin dependencies must use `provided` scope:** +```xml + + com.example + target-library + ${version} + provided + +``` + +**Agent core dependency policy:** +- New dependencies in agent core are treated with extreme caution +- Prefer using existing imported libraries already in the project +- Prefer JDK standard libraries over third-party libraries +- Plugins should rely on the target application's libraries (provided scope), not bundle them + +### Tracing Concepts + +#### Span Types +- **EntrySpan**: Service provider/endpoint (HTTP server, MQ consumer) +- **LocalSpan**: Internal method (no remote calls) +- **ExitSpan**: Client call (HTTP client, DB access, MQ producer) + +#### SpanLayer (required for EntrySpan/ExitSpan) +- `DB`: Database access +- `RPC_FRAMEWORK`: RPC calls (not ordinary HTTP) +- `HTTP`: HTTP calls +- `MQ`: Message queue +- `UNKNOWN`: Default + +#### Context Propagation +- **ContextCarrier**: Cross-process propagation (serialize to headers/attachments) +- **ContextSnapshot**: Cross-thread propagation (in-memory, no serialization) + +#### Required Span Attributes +For EntrySpan and ExitSpan, always set: +```java +span.setComponent(ComponentsDefine.YOUR_COMPONENT); +span.setLayer(SpanLayer.HTTP); // or DB, MQ, RPC_FRAMEWORK +``` + +#### Special Tags for OAP Analysis +| Tag | Purpose | +|-----|---------| +| `http.status_code` | HTTP response code (integer) | +| `db.type` | Database type (e.g., "sql", "redis") | +| `db.statement` | SQL/query statement (enables slow query analysis) | +| `cache.type`, `cache.op`, `cache.cmd`, `cache.key` | Cache metrics | +| `mq.queue`, `mq.topic` | MQ metrics | + +### Meter Plugin APIs + +For collecting numeric metrics (alternative to tracing): +```java +// Counter +Counter counter = MeterFactory.counter("metric_name") + .tag("key", "value") + .mode(Counter.Mode.INCREMENT) + .build(); +counter.increment(1d); + +// Gauge +Gauge gauge = MeterFactory.gauge("metric_name", () -> getValue()) + .tag("key", "value") + .build(); + +// Histogram +Histogram histogram = MeterFactory.histogram("metric_name") + .steps(Arrays.asList(1, 5, 10)) + .build(); +histogram.addValue(3); +``` + +### Data Flow +1. Agent attaches to JVM via `-javaagent` flag +2. ByteBuddy transforms target classes at load time +3. Interceptors collect span/trace data on method entry/exit +4. Data is buffered via DataCarrier +5. gRPC reporter sends data to OAP backend + +## Code Style & Conventions + +### Checkstyle Rules (enforced via `apm-checkstyle/checkStyle.xml`) + +**Prohibited patterns:** +- No `System.out.println` - use proper logging +- No `@author` tags - ASF projects don't use author annotations +- No Chinese characters in source files +- No tab characters (use 4 spaces) +- No star imports (`import xxx.*`) +- No unused or redundant imports + +**Required patterns:** +- `@Override` annotation required for overridden methods +- `equals()` and `hashCode()` must be overridden together +- Apache 2.0 license header on all source files + +**Naming conventions:** +- Constants/static variables: `UPPER_CASE_WITH_UNDERSCORES` +- Package names: `org.apache.skywalking.apm.*` or `test.apache.skywalking.apm.*` +- Type names: `PascalCase` +- Local variables/parameters/members: `camelCase` +- Plugin directories: `{framework}-{version}-plugin` +- Instrumentation classes: `*Instrumentation.java` +- Interceptor classes: `*Interceptor.java` + +**File limits:** +- Max file length: 3000 lines + +### Lombok Usage +Use Lombok annotations for boilerplate code: +- `@Getter`, `@Setter`, `@Data` +- `@Builder` +- `@Slf4j` for logging + +## Testing + +### Test Frameworks +- JUnit 4.12 for unit tests +- Mockito 5.0.0 for mocking + +### Test Categories + +**Unit Tests** (in each module's `src/test/java`) +- Standard JUnit tests +- Pattern: `*Test.java` + +**Plugin E2E Tests** (`test/plugin/scenarios/`) +- 100+ test scenarios for plugin validation +- Docker-based testing with actual frameworks +- Pattern: `{framework}-{version}-scenario` + +**End-to-End Tests** (`test/e2e/`) +- Full system integration testing + +### Running Tests +```bash +# Unit tests +./mvnw test + +# Full verification including checkstyle +./mvnw clean verify + +# Skip tests during build +./mvnw package -Dmaven.test.skip=true +``` + +### Plugin Test Framework + +The plugin test framework verifies plugin functionality using Docker containers with real services and a mock OAP backend. + +#### Environment Requirements +- MacOS/Linux +- JDK 8+ +- Docker & Docker Compose + +#### Test Case Structure + +**JVM-container (preferred):** +``` +{scenario}-scenario/ +├── bin/ +│ └── startup.sh # JVM startup script (required) +├── config/ +│ └── expectedData.yaml # Expected trace/meter/log data +├── src/main/java/... # Test application code +├── pom.xml +├── configuration.yml # Test case configuration +└── support-version.list # Supported versions (one per line) +``` + +**Tomcat-container:** +``` +{scenario}-scenario/ +├── config/ +│ └── expectedData.yaml +├── src/main/ +│ ├── java/... +│ └── webapp/WEB-INF/web.xml +├── pom.xml +├── configuration.yml +└── support-version.list +``` + +#### Key Configuration Files + +**configuration.yml:** +```yaml +type: jvm # or tomcat +entryService: http://localhost:8080/case # Entry endpoint (GET) +healthCheck: http://localhost:8080/health # Health check endpoint (HEAD) +startScript: ./bin/startup.sh # JVM-container only +runningMode: default # default|with_optional|with_bootstrap +withPlugins: apm-spring-annotation-plugin-*.jar # For optional/bootstrap modes +environment: + - KEY=value +dependencies: # External services (docker-compose style) + mysql: + image: mysql:8.0 + hostname: mysql + environment: + - MYSQL_ROOT_PASSWORD=root +``` + +**support-version.list:** +``` +# One version per line, use # for comments +# Only include ONE version per minor version (not all patch versions) +4.3.6 +4.4.1 +4.5.0 +``` + +**expectedData.yaml:** + +Trace and meter expectations are typically in separate scenarios. + +*For tracing plugins:* +```yaml +segmentItems: + - serviceName: your-scenario + segmentSize: ge 1 # Operators: eq, ge, gt, nq + segments: + - segmentId: not null + spans: + - operationName: /your/endpoint + parentSpanId: -1 # -1 for root span + spanId: 0 + spanLayer: Http # Http, DB, RPC_FRAMEWORK, MQ, CACHE, Unknown + spanType: Entry # Entry, Exit, Local + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + peer: '' # Empty string for Entry/Local, required for Exit + skipAnalysis: false + tags: + - {key: url, value: not null} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + logs: [] + refs: [] # SegmentRefs for cross-process/cross-thread +``` + +*For meter plugins:* +```yaml +meterItems: + - serviceName: your-scenario + meterSize: ge 1 + meters: + - meterId: + name: test_counter + tags: + - {name: key1, value: value1} # Note: uses 'name' not 'key' + singleValue: gt 0 # For counter/gauge + - meterId: + name: test_histogram + tags: + - {name: key1, value: value1} + histogramBuckets: # For histogram + - 0.0 + - 1.0 + - 5.0 + - 10.0 +``` + +**startup.sh (JVM-container):** +```bash +#!/bin/bash +home="$(cd "$(dirname $0)"; pwd)" +# ${agent_opts} is REQUIRED - contains agent parameters +java -jar ${agent_opts} ${home}/../libs/your-scenario.jar & +``` + +#### Running Plugin Tests Locally + +```bash +# Run a specific scenario +bash ./test/plugin/run.sh -f {scenario_name} + +# IMPORTANT: Rebuild agent if apm-sniffer code changed +./mvnw clean package -DskipTests -pl apm-sniffer + +# Use generator to create new test case +bash ./test/plugin/generator.sh +``` + +#### Adding Tests to CI + +Add scenario to the appropriate `.github/workflows/` file: +- Use `python3 tools/select-group.py` to find the file with fewest cases +- **JDK 8 tests**: `plugins-test..yaml` +- **JDK 17 tests**: `plugins-jdk17-test..yaml` +- **JDK 21 tests**: `plugins-jdk21-test..yaml` +- **JDK 25 tests**: `plugins-jdk25-test..yaml` + +```yaml +matrix: + case: + - your-scenario-scenario +``` + +#### Test Code Package Naming +- Test code: `org.apache.skywalking.apm.testcase.*` +- Code to be instrumented: `test.org.apache.skywalking.apm.testcase.*` + +## Git Submodules + +The project uses submodules for protocol definitions: +- `apm-protocol/apm-network/src/main/proto` - skywalking-data-collect-protocol + +Always use `--recurse-submodules` when cloning or update submodules manually: +```bash +git submodule init && git submodule update +``` + +## IDE Setup (IntelliJ IDEA) + +1. Import as Maven project +2. Run `./mvnw compile -Dmaven.test.skip=true` to generate protobuf sources +3. Mark generated source folders: + - `*/target/generated-sources/protobuf/java` + - `*/target/generated-sources/protobuf/grpc-java` +4. Enable annotation processing for Lombok + +## Key Files for Understanding the Codebase + +- `apm-sniffer/apm-agent/` - Agent entry point (premain) +- `apm-sniffer/apm-agent-core/src/main/java/.../enhance/` - Instrumentation engine +- `apm-sniffer/apm-agent-core/src/main/java/.../plugin/` - Plugin loading system +- `apm-sniffer/apm-sdk-plugin/` - All standard plugins (reference implementations) +- `apm-sniffer/config/agent.config` - Default agent configuration + +## Common Development Tasks + +### Adding a New Plugin +1. Create directory in `apm-sniffer/apm-sdk-plugin/{framework}-{version}-plugin/` +2. Implement instrumentation class using **V2 API** (e.g., extend `ClassInstanceMethodsEnhancePluginDefineV2`) +3. Implement interceptor class using **V2 API** (e.g., implement `InstanceMethodsAroundInterceptorV2`) +4. Register plugin in `skywalking-plugin.def` file +5. Add test scenario in `test/plugin/scenarios/` + +### Adding an Optional Plugin +1. Create in `apm-sniffer/optional-plugins/` +2. Update documentation in `docs/en/setup/service-agent/java-agent/Optional-plugins.md` + +### Modifying Agent Configuration +1. Edit `apm-sniffer/config/agent.config` +2. Update documentation if adding new options + +## Documentation + +- `docs/en/setup/service-agent/java-agent/` - Main agent documentation +- `docs/en/setup/service-agent/java-agent/Plugin-list.md` - Complete plugin list +- `docs/en/setup/service-agent/java-agent/Optional-plugins.md` - Optional plugins guide +- `CHANGES.md` - Changelog (update when making changes) + +## Community + +- GitHub Issues: https://github.com/apache/skywalking-java/issues +- Mailing List: dev@skywalking.apache.org +- Slack: #skywalking channel at Apache Slack + +## Submitting Pull Requests + +### Branch Strategy +- **Never work directly on main branch** +- Create a new branch for your changes + +### PR Template +Follow `.github/PULL_REQUEST_TEMPLATE` based on change type: +- **Bug fix**: Add unit test, explain bug cause and fix +- **New plugin**: Add test case, component ID in OAP, logo in UI repo +- **Performance improvement**: Add benchmark with results, link to theory/discussion +- **New feature**: Link design doc if non-trivial, update docs, add tests + +### PR Requirements +- Follow Apache Code of Conduct +- Include updated documentation for new features +- Include tests for new functionality +- Reference original issue (e.g., "Resolves #123") +- Update `CHANGES.md` for user-facing changes +- Pass all CI checks (checkstyle, tests, license headers) + +### PR Description +- Bug fixes: Explain the bug and how it's fixed, add regression test +- New features: Link to design doc if non-trivial, update docs, add tests +- Do NOT add AI assistant as co-author + +## CI/CD + +GitHub Actions workflows: +- **CI**: Multi-OS (Ubuntu, macOS, Windows), Multi-Java (8, 11, 17, 21, 25) +- **Plugin Tests**: Parallel E2E tests for all plugins +- **E2E Tests**: Full system integration +- **Docker Publishing**: Multi-variant images + +## Tips for AI Assistants + +1. **Use V2 instrumentation API**: Always use V2 classes (`ClassEnhancePluginDefineV2`, `InstanceMethodsAroundInterceptorV2`) for new plugins; V1 is legacy +2. **NEVER use `.class` references**: In instrumentation definitions, always use string literals for class names (e.g., `byName("com.example.MyClass")` not `byName(MyClass.class.getName())`) +3. **Always set component and layer**: For EntrySpan and ExitSpan, always call `setComponent()` and `setLayer()` +4. **Prefer `byName` for class matching**: Avoid `byHierarchyMatch` unless necessary (causes performance issues) +5. **Use witness classes for version-specific plugins**: Implement `witnessClasses()` or `witnessMethods()` to activate plugins only for specific library versions +6. **Always check submodules**: Protocol changes may require submodule updates +7. **Generate sources first**: Run `mvnw compile` before analyzing generated code +8. **Respect checkstyle**: No System.out, no @author, no Chinese characters +9. **Follow plugin patterns**: Use existing V2 plugins as templates +10. **Use Lombok**: Prefer annotations over boilerplate code +11. **Test both unit and E2E**: Different test patterns for different scopes +12. **Plugin naming**: Follow `{framework}-{version}-plugin` convention +13. **Shaded dependencies**: Core dependencies are shaded to avoid classpath conflicts +14. **Java version compatibility**: Agent core must maintain Java 8 compatibility, but individual plugins may target higher JDK versions (e.g., jdk-httpclient-plugin for JDK 11+, virtual-thread plugins for JDK 21+) +15. **Bootstrap instrumentation**: Only use for JDK core classes, and only when absolutely necessary +16. **Register plugins**: Always add plugin definition to `skywalking-plugin.def` file From 69899af59353a6af9d2f227a8b1ad30423fa4ecd Mon Sep 17 00:00:00 2001 From: Siman-hub <118841469+Siman-hub@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:58:37 +0530 Subject: [PATCH 088/114] [Test] Add Spring Cloud Gateway 4.3.3 to gateway scenario (#787) * test(gateway-4.3.x): add scenario coverage for 4.3.x * test(plugin): install bash in agent-test-jvm image and add gateway 4.3.x scenario --- changes/changes-9.5.0.md | 1 + .../java-agent/Supported-list.md | 2 +- test/plugin/containers/jvm-container/pom.xml | 2 +- test/plugin/run.sh | 2 + .../config/expectedData.yaml | 189 ++++++++++++++++++ .../gateway-4.3.x-scenario/configuration.yml | 23 +++ .../gateway-dist/bin/startup.sh | 24 +++ .../gateway-dist/pom.xml | 57 ++++++ .../src/main/assembly/assembly.xml | 47 +++++ .../gateway-projectA-scenario/pom.xml | 56 ++++++ .../sc/gateway/projectA/ApiKeyResolver.java | 31 +++ .../sc/gateway/projectA/Application.java | 29 +++ .../sc/gateway/projectA/Test1Filter.java | 38 ++++ .../sc/gateway/projectA/Test2Filter.java | 39 ++++ .../sc/gateway/projectA/TestFilterConfig.java | 35 ++++ .../src/main/resources/application.yml | 33 +++ .../gateway-projectB-scenario/pom.xml | 57 ++++++ .../sc/gateway/projectB/Application.java | 31 +++ .../projectB/controller/TestController.java | 40 ++++ .../src/main/resources/application.properties | 17 ++ .../scenarios/gateway-4.3.x-scenario/pom.xml | 79 ++++++++ .../support-version.list | 17 ++ 22 files changed, 847 insertions(+), 2 deletions(-) create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/bin/startup.sh create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/pom.xml create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/pom.xml create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/pom.xml create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/gateway-4.3.x-scenario/support-version.list diff --git a/changes/changes-9.5.0.md b/changes/changes-9.5.0.md index ff5133d250..01ff913873 100644 --- a/changes/changes-9.5.0.md +++ b/changes/changes-9.5.0.md @@ -20,6 +20,7 @@ Release Notes. * Fix the `CreateAopProxyInterceptor` in the Spring core-patch changes the AOP proxy type when a class is enhanced by both SkyWalking and Spring AOP. * Build: Centralized plugin version management in the root POM and remove redundant declarations. +* Support Spring Cloud Gateway 4.3.x. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 63369af6ea..bb841000a4 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -42,7 +42,7 @@ metrics based on the tracing data. * [Hutool-http](https://www.hutool.cn/) client 5.x * [Micronaut HTTP Client](https://github.com/micronaut-projects/micronaut-core) 3.2.x -> 3.6.x * HTTP Gateway - * [Spring Cloud Gateway](https://spring.io/projects/spring-cloud-gateway) 2.0.2.RELEASE -> 4.1.x (Optional²) + * [Spring Cloud Gateway](https://spring.io/projects/spring-cloud-gateway) 2.0.2.RELEASE -> 4.3.x (Optional²) * [Apache ShenYu](https://shenyu.apache.org) (Rich protocol support: `HTTP`,`Spring Cloud`,`gRPC`,`Dubbo`,`SOFARPC`,`Motan`,`Tars`) 2.4.x (Optional²) * JDBC * Mysql Driver 5.x, 6.x, 8.x diff --git a/test/plugin/containers/jvm-container/pom.xml b/test/plugin/containers/jvm-container/pom.xml index 65d4045469..e71083c86e 100644 --- a/test/plugin/containers/jvm-container/pom.xml +++ b/test/plugin/containers/jvm-container/pom.xml @@ -53,7 +53,7 @@ chmod +x /usr/local/skywalking/run.sh tar -xvf ../tools/skywalking-mock-collector.tar.gz -C ../tools apt-get update -y - apt-get install -y unzip + apt-get install -y unzip bash rm -rf /var/lib/apt/lists/* ["/usr/local/skywalking/run.sh"] diff --git a/test/plugin/run.sh b/test/plugin/run.sh index 47a87de456..164eebfe6d 100755 --- a/test/plugin/run.sh +++ b/test/plugin/run.sh @@ -159,6 +159,8 @@ remove_dir() { start_stamp=`date +%s` parse_commandline "$@" +echo "Scenario=$scenario_name JavaImage=$base_image_java TomcatImage=$base_image_tomcat" + if [[ "$cleanup" == "on" ]]; then do_cleanup [[ -z "${scenario_name}" ]] && exit 0 diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-4.3.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..94488a65aa --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/config/expectedData.yaml @@ -0,0 +1,189 @@ + # 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. + + ignoreSegmentNames: + - HEAD:/provider/b/healthCheck + - /provider/b/healthCheck + + segmentItems: + - serviceName: gateway-projectB-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: GET:/provider/b/testcase + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: not null} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: SpringCloudGateway/GatewayFilter, networkAddress: not null, + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' + + - serviceName: gateway-projectA-scenario + segmentSize: nq 0 + segments: + # -------------------------------------------------------- + # Case 1: Timeout Error + # -------------------------------------------------------- + # A. Entry Span + - segmentId: not null + spans: + - operationName: /provider/timeout/error + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: true + spanType: Entry + peer: '' + tags: + - {key: url, value: not null } + - {key: http.method, value: GET} + - {key: http.status_code, value: '500'} + skipAnalysis: 'false' + + # B. Exit Span (Contains Logs) + - segmentId: not null + spans: + - operationName: SpringCloudGateway/sendRequest + parentSpanId: 1 + spanId: 2 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: true + spanType: Exit + peer: not null + skipAnalysis: 'false' + tags: + - { key: url, value: not null } + logs: + - logEvent: + - { key: event, value: error } + - { key: error.kind, value: not null } + - { key: message, value: not null } + - { key: stack, value: not null} + - operationName: SpringCloudGateway/RoutingFilter + parentSpanId: 0 + spanId: 1 + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + refs: + - { parentEndpoint: '/provider/timeout/error', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + - operationName: SpringCloudGateway/GatewayFilter + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + refs: + - { parentEndpoint: '/provider/timeout/error', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + + # -------------------------------------------------------- + # Case 2: Success Case + # -------------------------------------------------------- + # A. Entry Span + - segmentId: not null + spans: + - operationName: /provider/b/testcase + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: false + spanType: Entry + peer: '' + tags: + - { key: url, value: not null } + - { key: http.method, value: GET } + - { key: http.status_code, value: '200' } + skipAnalysis: 'false' + + # B. Exit Span + - segmentId: not null + spans: + - operationName: SpringCloudGateway/sendRequest + parentSpanId: 1 + spanId: 2 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: false + spanType: Exit + peer: not null + tags: + - {key: url, value: not null} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: SpringCloudGateway/RoutingFilter + parentSpanId: 0 + spanId: 1 + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + refs: + - {parentEndpoint: '/provider/b/testcase', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + - operationName: SpringCloudGateway/GatewayFilter + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + refs: + - {parentEndpoint: '/provider/b/testcase', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/configuration.yml b/test/plugin/scenarios/gateway-4.3.x-scenario/configuration.yml new file mode 100644 index 0000000000..49d08ed8ef --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/configuration.yml @@ -0,0 +1,23 @@ +# 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/provider/b/testcase +healthCheck: http://localhost:8080/provider/b/healthCheck +startScript: ./bin/startup.sh +runningMode: with_optional +withPlugins: apm-spring-cloud-gateway-4.x-plugin-*.jar + diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/bin/startup.sh b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/bin/startup.sh new file mode 100644 index 0000000000..0d28675632 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/bin/startup.sh @@ -0,0 +1,24 @@ +#!/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} "-Dskywalking.agent.service_name=gateway-projectA-scenario" ${home}/../libs/gateway-projectA-scenario.jar & +sleep 1 + +java -jar ${agent_opts} "-Dskywalking.agent.service_name=gateway-projectB-scenario" ${home}/../libs/gateway-projectB-scenario.jar & diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/pom.xml b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/pom.xml new file mode 100644 index 0000000000..45b02e8800 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/pom.xml @@ -0,0 +1,57 @@ + + + + + org.apache.skywalking + gateway-4.3.x-scenario + 5.0.0 + + 4.0.0 + + gateway-dist + + + gateway-4.3.x-scenario + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + gateway-4.3.x-scenario + false + + src/main/assembly/assembly.xml + + ../target/ + + + + + + + diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/src/main/assembly/assembly.xml b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..127200bdc8 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-dist/src/main/assembly/assembly.xml @@ -0,0 +1,47 @@ + + + + gateway-dist + + zip + + + + + ./bin + 0775 + + + + + + ../gateway-projectA-scenario/target/gateway-projectA-scenario.jar + ./libs + 0775 + + + ../gateway-projectB-scenario/target/gateway-projectB-scenario.jar + ./libs + 0775 + + + \ No newline at end of file diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/pom.xml b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/pom.xml new file mode 100644 index 0000000000..a3009bea02 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/pom.xml @@ -0,0 +1,56 @@ + + + + + org.apache.skywalking + gateway-4.3.x-scenario + 5.0.0 + + 4.0.0 + + gateway-projectA-scenario + + + + org.springframework.cloud + spring-cloud-starter-gateway + ${test.framework.version} + + + + + gateway-projectA-scenario + + + org.springframework.boot + spring-boot-maven-plugin + 3.0.0 + + + + repackage + + + + + + + diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java new file mode 100644 index 0000000000..40517d1d3f --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java @@ -0,0 +1,31 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +@Component +public class ApiKeyResolver implements KeyResolver { + + public Mono resolve(ServerWebExchange exchange) { + return Mono.just(exchange.getRequest().getPath().value()); + } +} diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java new file mode 100644 index 0000000000..68eb95b0c6 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java @@ -0,0 +1,29 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java new file mode 100644 index 0000000000..af891eae20 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java @@ -0,0 +1,38 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +public class Test1Filter implements GlobalFilter, Ordered { + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest buildRequest = exchange.getRequest().mutate().build(); + return chain.filter(exchange.mutate().request(buildRequest).build()); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java new file mode 100644 index 0000000000..d3a5846bd5 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java @@ -0,0 +1,39 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +public class Test2Filter implements GlobalFilter, Ordered { + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest buildRequest = exchange.getRequest().mutate().build(); + return chain.filter(exchange.mutate().request(buildRequest).build()); + } + + @Override + public int getOrder() { + return 1; + } +} diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java new file mode 100644 index 0000000000..29f9627bdf --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java @@ -0,0 +1,35 @@ +/* + * 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.sc.gateway.projectA; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class TestFilterConfig { + + @Bean + public Test1Filter test1Filter() { + return new Test1Filter(); + } + + @Bean + public Test2Filter test2Filter() { + return new Test2Filter(); + } +} diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml new file mode 100644 index 0000000000..7639e7ce8a --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml @@ -0,0 +1,33 @@ +# +# 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 +spring: + cloud: + gateway: + httpclient: + connect-timeout: 2000 + routes: + - id: provider_route + uri: http://localhost:18070 + predicates: + - Path=/provider/b/* + - id: provider_timeout + uri: http://1.2.3.4:18070 + predicates: + - Path=/provider/timeout/* diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/pom.xml b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/pom.xml new file mode 100644 index 0000000000..2e1b7cb3d7 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/pom.xml @@ -0,0 +1,57 @@ + + + + + gateway-4.3.x-scenario + org.apache.skywalking + 5.0.0 + + 4.0.0 + + gateway-projectB-scenario + + + + org.springframework.boot + spring-boot-starter-web + 2.1.0.RELEASE + + + + + gateway-projectB-scenario + + + org.springframework.boot + spring-boot-maven-plugin + 1.5.9.RELEASE + + + + repackage + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java new file mode 100644 index 0000000000..51c94655c7 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java @@ -0,0 +1,31 @@ +/* + * 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.sc.gateway.projectB; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(value = {"test.apache.skywalking.apm.testcase.sc.gateway.projectB.controller"}) +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java new file mode 100644 index 0000000000..923d7fd7ff --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java @@ -0,0 +1,40 @@ +/* + * 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.sc.gateway.projectB.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; + +@RestController +public class TestController { + + @RequestMapping("/provider/b/testcase") + public String testcase() { + try { + new RestTemplate().getForEntity("http://localhost:8080/provider/timeout/error", String.class); + } catch (Exception e) { + } + return "1"; + } + + @RequestMapping("/provider/b/healthCheck") + public String healthCheck() { + return "Success"; + } +} diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties new file mode 100644 index 0000000000..cac2c4d5a1 --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties @@ -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. +# +server.port=18070 \ No newline at end of file diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/pom.xml b/test/plugin/scenarios/gateway-4.3.x-scenario/pom.xml new file mode 100644 index 0000000000..a91ec5a97d --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-scenario/pom.xml @@ -0,0 +1,79 @@ + + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.2.5 + + + + org.apache.skywalking + gateway-4.3.x-scenario + pom + 5.0.0 + + gateway-projectA-scenario + gateway-projectB-scenario + gateway-dist + + + skywalking-gateway-4.3.x-scenario + + + UTF-8 + 17 + 2023.0.0 + 3.11.0 + 4.3.3 + ${test.framework.version} + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + gateway-4.3.x-scenario + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + + + diff --git a/test/plugin/scenarios/gateway-4.3.x-scenario/support-version.list b/test/plugin/scenarios/gateway-4.3.x-scenario/support-version.list new file mode 100644 index 0000000000..ab039a217d --- /dev/null +++ b/test/plugin/scenarios/gateway-4.3.x-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. + +4.3.3 \ No newline at end of file From ea25bfeb9ce54f7faa4fbc8e2580be500c312785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Thu, 12 Feb 2026 23:52:31 +0800 Subject: [PATCH 089/114] Split plugin development guide from root CLAUDE.md into module-level files (#790) Move plugin development content (V2/V1 APIs, class matching, tracing concepts, meter APIs, plugin test framework, etc.) into dedicated CLAUDE.md files under apm-sniffer/apm-sdk-plugin/ and apm-sniffer/bootstrap-plugins/, reducing the root CLAUDE.md from ~700 lines to ~300 lines for better maintainability. --- CLAUDE.md | 423 +----------------------- apm-sniffer/apm-sdk-plugin/CLAUDE.md | 401 ++++++++++++++++++++++ apm-sniffer/bootstrap-plugins/CLAUDE.md | 53 +++ 3 files changed, 465 insertions(+), 412 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/CLAUDE.md create mode 100644 apm-sniffer/bootstrap-plugins/CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md index 90e3bf0f6c..02c69c17e3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -110,11 +110,12 @@ The agent uses ByteBuddy for bytecode manipulation at runtime: **1. SDK Plugins** (`apm-sniffer/apm-sdk-plugin/`) - Framework-specific instrumentations (70+ plugins) - Examples: grpc-1.x, spring, dubbo, mybatis, mongodb, redis, etc. -- Pattern: One directory per library/framework version +- See `apm-sniffer/apm-sdk-plugin/CLAUDE.md` for plugin development guide **2. Bootstrap Plugins** (`apm-sniffer/bootstrap-plugins/`) - Load at JVM bootstrap phase for JDK-level instrumentation - Examples: jdk-threading, jdk-http, jdk-httpclient, jdk-virtual-thread-executor +- See `apm-sniffer/bootstrap-plugins/CLAUDE.md` for bootstrap plugin guide **3. Optional Plugins** (`apm-sniffer/optional-plugins/`) - Not included by default, user must copy to plugins directory @@ -122,237 +123,6 @@ The agent uses ByteBuddy for bytecode manipulation at runtime: **4. Optional Reporter Plugins** (`apm-sniffer/optional-reporter-plugins/`) - Alternative data collection backends (e.g., Kafka) -### Plugin Instrumentation APIs (v1 vs v2) - -The agent provides two instrumentation APIs. **V2 is recommended** for all new plugins; v1 is legacy and should only be used for maintaining existing plugins. - -#### V2 API (Recommended) - -V2 provides a `MethodInvocationContext` that is shared across all interception phases (`beforeMethod`, `afterMethod`, `handleMethodException`), allowing you to pass data (e.g., spans) between phases. - -**Instrumentation class (extends `ClassEnhancePluginDefineV2`):** -```java -public class XxxInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 { - @Override - protected ClassMatch enhanceClass() { - return NameMatch.byName("target.class.Name"); - } - - @Override - public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[] { ... }; - } - - @Override - public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { - return new InstanceMethodsInterceptV2Point[] { - new InstanceMethodsInterceptV2Point() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("targetMethod"); - } - - @Override - public String getMethodsInterceptorV2() { - return "org.apache.skywalking.apm.plugin.xxx.XxxInterceptor"; - } - - @Override - public boolean isOverrideArgs() { - return false; - } - } - }; - } -} -``` - -**Interceptor class (implements `InstanceMethodsAroundInterceptorV2`):** -```java -public class XxxInterceptor implements InstanceMethodsAroundInterceptorV2 { - @Override - public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, MethodInvocationContext context) { - // Create span and store in context for later use - AbstractSpan span = ContextManager.createLocalSpan("operationName"); - context.setContext(span); // Pass to afterMethod/handleMethodException - } - - @Override - public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Object ret, MethodInvocationContext context) { - // Retrieve span from context - AbstractSpan span = (AbstractSpan) context.getContext(); - span.asyncFinish(); - return ret; - } - - @Override - public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { - AbstractSpan span = (AbstractSpan) context.getContext(); - span.log(t); - } -} -``` - -**Key V2 classes:** -- `ClassEnhancePluginDefineV2` - Base class for plugins with both instance and static methods -- `ClassInstanceMethodsEnhancePluginDefineV2` - For instance methods only -- `ClassStaticMethodsEnhancePluginDefineV2` - For static methods only -- `InstanceMethodsAroundInterceptorV2` - Interceptor interface with `MethodInvocationContext` -- `StaticMethodsAroundInterceptorV2` - Static method interceptor with context - -#### V1 API (Legacy) - -V1 uses `MethodInterceptResult` only in `beforeMethod` and has no shared context between phases. **Only use for maintaining existing legacy plugins.** - -**Key V1 classes (legacy):** -- `ClassEnhancePluginDefine` -- `ClassInstanceMethodsEnhancePluginDefine` -- `ClassStaticMethodsEnhancePluginDefine` -- `InstanceMethodsAroundInterceptor` -- `StaticMethodsAroundInterceptor` - -### Plugin Development Rules - -#### Class Matching Restrictions - -**CRITICAL: Never use `.class` references in instrumentation definitions:** -```java -// WRONG - will break the agent if ThirdPartyClass doesn't exist -takesArguments(ThirdPartyClass.class) -byName(ThirdPartyClass.class.getName()) - -// CORRECT - use string literals -takesArguments("com.example.ThirdPartyClass") -byName("com.example.ThirdPartyClass") -``` - -**ClassMatch options:** -- `byName(String)`: Match by full class name (package + class name) - **preferred** -- `byClassAnnotationMatch`: Match classes with specific annotations (does NOT support inherited annotations) -- `byMethodAnnotationMatch`: Match classes with methods having specific annotations -- `byHierarchyMatch`: Match by parent class/interface - **avoid unless necessary** (performance impact) - -#### Witness Classes/Methods - -Use witness classes/methods to activate plugins only for specific library versions: -```java -@Override -protected String[] witnessClasses() { - return new String[] { "com.example.VersionSpecificClass" }; -} - -@Override -protected List witnessMethods() { - return Collections.singletonList( - new WitnessMethod("com.example.SomeClass", ElementMatchers.named("specificMethod")) - ); -} -``` - -#### Bootstrap Instrumentation - -For JDK core classes (rt.jar), override `isBootstrapInstrumentation()`: -```java -@Override -public boolean isBootstrapInstrumentation() { - return true; -} -``` -**WARNING**: Use bootstrap instrumentation only where absolutely necessary. - -#### Plugin Configuration - -Use `@PluginConfig` annotation for custom plugin settings: -```java -public class MyPluginConfig { - public static class Plugin { - @PluginConfig(root = MyPluginConfig.class) - public static class MyPlugin { - public static boolean SOME_SETTING = false; - } - } -} -``` -Config key becomes: `plugin.myplugin.some_setting` - -#### Dependency Management - -**Plugin dependencies must use `provided` scope:** -```xml - - com.example - target-library - ${version} - provided - -``` - -**Agent core dependency policy:** -- New dependencies in agent core are treated with extreme caution -- Prefer using existing imported libraries already in the project -- Prefer JDK standard libraries over third-party libraries -- Plugins should rely on the target application's libraries (provided scope), not bundle them - -### Tracing Concepts - -#### Span Types -- **EntrySpan**: Service provider/endpoint (HTTP server, MQ consumer) -- **LocalSpan**: Internal method (no remote calls) -- **ExitSpan**: Client call (HTTP client, DB access, MQ producer) - -#### SpanLayer (required for EntrySpan/ExitSpan) -- `DB`: Database access -- `RPC_FRAMEWORK`: RPC calls (not ordinary HTTP) -- `HTTP`: HTTP calls -- `MQ`: Message queue -- `UNKNOWN`: Default - -#### Context Propagation -- **ContextCarrier**: Cross-process propagation (serialize to headers/attachments) -- **ContextSnapshot**: Cross-thread propagation (in-memory, no serialization) - -#### Required Span Attributes -For EntrySpan and ExitSpan, always set: -```java -span.setComponent(ComponentsDefine.YOUR_COMPONENT); -span.setLayer(SpanLayer.HTTP); // or DB, MQ, RPC_FRAMEWORK -``` - -#### Special Tags for OAP Analysis -| Tag | Purpose | -|-----|---------| -| `http.status_code` | HTTP response code (integer) | -| `db.type` | Database type (e.g., "sql", "redis") | -| `db.statement` | SQL/query statement (enables slow query analysis) | -| `cache.type`, `cache.op`, `cache.cmd`, `cache.key` | Cache metrics | -| `mq.queue`, `mq.topic` | MQ metrics | - -### Meter Plugin APIs - -For collecting numeric metrics (alternative to tracing): -```java -// Counter -Counter counter = MeterFactory.counter("metric_name") - .tag("key", "value") - .mode(Counter.Mode.INCREMENT) - .build(); -counter.increment(1d); - -// Gauge -Gauge gauge = MeterFactory.gauge("metric_name", () -> getValue()) - .tag("key", "value") - .build(); - -// Histogram -Histogram histogram = MeterFactory.histogram("metric_name") - .steps(Arrays.asList(1, 5, 10)) - .build(); -histogram.addValue(3); -``` - ### Data Flow 1. Agent attaches to JVM via `-javaagent` flag 2. ByteBuddy transforms target classes at load time @@ -411,6 +181,7 @@ Use Lombok annotations for boilerplate code: - 100+ test scenarios for plugin validation - Docker-based testing with actual frameworks - Pattern: `{framework}-{version}-scenario` +- See `apm-sniffer/apm-sdk-plugin/CLAUDE.md` for full test framework documentation **End-to-End Tests** (`test/e2e/`) - Full system integration testing @@ -427,165 +198,6 @@ Use Lombok annotations for boilerplate code: ./mvnw package -Dmaven.test.skip=true ``` -### Plugin Test Framework - -The plugin test framework verifies plugin functionality using Docker containers with real services and a mock OAP backend. - -#### Environment Requirements -- MacOS/Linux -- JDK 8+ -- Docker & Docker Compose - -#### Test Case Structure - -**JVM-container (preferred):** -``` -{scenario}-scenario/ -├── bin/ -│ └── startup.sh # JVM startup script (required) -├── config/ -│ └── expectedData.yaml # Expected trace/meter/log data -├── src/main/java/... # Test application code -├── pom.xml -├── configuration.yml # Test case configuration -└── support-version.list # Supported versions (one per line) -``` - -**Tomcat-container:** -``` -{scenario}-scenario/ -├── config/ -│ └── expectedData.yaml -├── src/main/ -│ ├── java/... -│ └── webapp/WEB-INF/web.xml -├── pom.xml -├── configuration.yml -└── support-version.list -``` - -#### Key Configuration Files - -**configuration.yml:** -```yaml -type: jvm # or tomcat -entryService: http://localhost:8080/case # Entry endpoint (GET) -healthCheck: http://localhost:8080/health # Health check endpoint (HEAD) -startScript: ./bin/startup.sh # JVM-container only -runningMode: default # default|with_optional|with_bootstrap -withPlugins: apm-spring-annotation-plugin-*.jar # For optional/bootstrap modes -environment: - - KEY=value -dependencies: # External services (docker-compose style) - mysql: - image: mysql:8.0 - hostname: mysql - environment: - - MYSQL_ROOT_PASSWORD=root -``` - -**support-version.list:** -``` -# One version per line, use # for comments -# Only include ONE version per minor version (not all patch versions) -4.3.6 -4.4.1 -4.5.0 -``` - -**expectedData.yaml:** - -Trace and meter expectations are typically in separate scenarios. - -*For tracing plugins:* -```yaml -segmentItems: - - serviceName: your-scenario - segmentSize: ge 1 # Operators: eq, ge, gt, nq - segments: - - segmentId: not null - spans: - - operationName: /your/endpoint - parentSpanId: -1 # -1 for root span - spanId: 0 - spanLayer: Http # Http, DB, RPC_FRAMEWORK, MQ, CACHE, Unknown - spanType: Entry # Entry, Exit, Local - startTime: nq 0 - endTime: nq 0 - componentId: 1 - isError: false - peer: '' # Empty string for Entry/Local, required for Exit - skipAnalysis: false - tags: - - {key: url, value: not null} - - {key: http.method, value: GET} - - {key: http.status_code, value: '200'} - logs: [] - refs: [] # SegmentRefs for cross-process/cross-thread -``` - -*For meter plugins:* -```yaml -meterItems: - - serviceName: your-scenario - meterSize: ge 1 - meters: - - meterId: - name: test_counter - tags: - - {name: key1, value: value1} # Note: uses 'name' not 'key' - singleValue: gt 0 # For counter/gauge - - meterId: - name: test_histogram - tags: - - {name: key1, value: value1} - histogramBuckets: # For histogram - - 0.0 - - 1.0 - - 5.0 - - 10.0 -``` - -**startup.sh (JVM-container):** -```bash -#!/bin/bash -home="$(cd "$(dirname $0)"; pwd)" -# ${agent_opts} is REQUIRED - contains agent parameters -java -jar ${agent_opts} ${home}/../libs/your-scenario.jar & -``` - -#### Running Plugin Tests Locally - -```bash -# Run a specific scenario -bash ./test/plugin/run.sh -f {scenario_name} - -# IMPORTANT: Rebuild agent if apm-sniffer code changed -./mvnw clean package -DskipTests -pl apm-sniffer - -# Use generator to create new test case -bash ./test/plugin/generator.sh -``` - -#### Adding Tests to CI - -Add scenario to the appropriate `.github/workflows/` file: -- Use `python3 tools/select-group.py` to find the file with fewest cases -- **JDK 8 tests**: `plugins-test..yaml` -- **JDK 17 tests**: `plugins-jdk17-test..yaml` -- **JDK 21 tests**: `plugins-jdk21-test..yaml` -- **JDK 25 tests**: `plugins-jdk25-test..yaml` - -```yaml -matrix: - case: - - your-scenario-scenario -``` - -#### Test Code Package Naming -- Test code: `org.apache.skywalking.apm.testcase.*` -- Code to be instrumented: `test.org.apache.skywalking.apm.testcase.*` - ## Git Submodules The project uses submodules for protocol definitions: @@ -616,11 +228,7 @@ git submodule init && git submodule update ## Common Development Tasks ### Adding a New Plugin -1. Create directory in `apm-sniffer/apm-sdk-plugin/{framework}-{version}-plugin/` -2. Implement instrumentation class using **V2 API** (e.g., extend `ClassInstanceMethodsEnhancePluginDefineV2`) -3. Implement interceptor class using **V2 API** (e.g., implement `InstanceMethodsAroundInterceptorV2`) -4. Register plugin in `skywalking-plugin.def` file -5. Add test scenario in `test/plugin/scenarios/` +See `apm-sniffer/apm-sdk-plugin/CLAUDE.md` for detailed guide. ### Adding an Optional Plugin 1. Create in `apm-sniffer/optional-plugins/` @@ -679,19 +287,10 @@ GitHub Actions workflows: ## Tips for AI Assistants -1. **Use V2 instrumentation API**: Always use V2 classes (`ClassEnhancePluginDefineV2`, `InstanceMethodsAroundInterceptorV2`) for new plugins; V1 is legacy -2. **NEVER use `.class` references**: In instrumentation definitions, always use string literals for class names (e.g., `byName("com.example.MyClass")` not `byName(MyClass.class.getName())`) -3. **Always set component and layer**: For EntrySpan and ExitSpan, always call `setComponent()` and `setLayer()` -4. **Prefer `byName` for class matching**: Avoid `byHierarchyMatch` unless necessary (causes performance issues) -5. **Use witness classes for version-specific plugins**: Implement `witnessClasses()` or `witnessMethods()` to activate plugins only for specific library versions -6. **Always check submodules**: Protocol changes may require submodule updates -7. **Generate sources first**: Run `mvnw compile` before analyzing generated code -8. **Respect checkstyle**: No System.out, no @author, no Chinese characters -9. **Follow plugin patterns**: Use existing V2 plugins as templates -10. **Use Lombok**: Prefer annotations over boilerplate code -11. **Test both unit and E2E**: Different test patterns for different scopes -12. **Plugin naming**: Follow `{framework}-{version}-plugin` convention -13. **Shaded dependencies**: Core dependencies are shaded to avoid classpath conflicts -14. **Java version compatibility**: Agent core must maintain Java 8 compatibility, but individual plugins may target higher JDK versions (e.g., jdk-httpclient-plugin for JDK 11+, virtual-thread plugins for JDK 21+) -15. **Bootstrap instrumentation**: Only use for JDK core classes, and only when absolutely necessary -16. **Register plugins**: Always add plugin definition to `skywalking-plugin.def` file +1. **Always check submodules**: Protocol changes may require submodule updates +2. **Generate sources first**: Run `mvnw compile` before analyzing generated code +3. **Respect checkstyle**: No System.out, no @author, no Chinese characters +4. **Use Lombok**: Prefer annotations over boilerplate code +5. **Test both unit and E2E**: Different test patterns for different scopes +6. **Java version compatibility**: Agent core must maintain Java 8 compatibility, but individual plugins may target higher JDK versions (e.g., jdk-httpclient-plugin for JDK 11+, virtual-thread plugins for JDK 21+) +7. **For plugin development**: See `apm-sniffer/apm-sdk-plugin/CLAUDE.md` and `apm-sniffer/bootstrap-plugins/CLAUDE.md` diff --git a/apm-sniffer/apm-sdk-plugin/CLAUDE.md b/apm-sniffer/apm-sdk-plugin/CLAUDE.md new file mode 100644 index 0000000000..a0c73a2a04 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/CLAUDE.md @@ -0,0 +1,401 @@ +# CLAUDE.md - SDK Plugin Development Guide + +This guide covers developing standard SDK plugins in `apm-sniffer/apm-sdk-plugin/`. + +## Plugin Instrumentation APIs (v1 vs v2) + +The agent provides two instrumentation APIs. **V2 is recommended** for all new plugins; v1 is legacy and should only be used for maintaining existing plugins. + +### V2 API (Recommended) + +V2 provides a `MethodInvocationContext` that is shared across all interception phases (`beforeMethod`, `afterMethod`, `handleMethodException`), allowing you to pass data (e.g., spans) between phases. + +**Instrumentation class (extends `ClassEnhancePluginDefineV2`):** +```java +public class XxxInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 { + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName("target.class.Name"); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { ... }; + } + + @Override + public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { + return new InstanceMethodsInterceptV2Point[] { + new InstanceMethodsInterceptV2Point() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("targetMethod"); + } + + @Override + public String getMethodsInterceptorV2() { + return "org.apache.skywalking.apm.plugin.xxx.XxxInterceptor"; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} +``` + +**Interceptor class (implements `InstanceMethodsAroundInterceptorV2`):** +```java +public class XxxInterceptor implements InstanceMethodsAroundInterceptorV2 { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInvocationContext context) { + AbstractSpan span = ContextManager.createLocalSpan("operationName"); + context.setContext(span); // Pass to afterMethod/handleMethodException + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret, MethodInvocationContext context) { + AbstractSpan span = (AbstractSpan) context.getContext(); + span.asyncFinish(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { + AbstractSpan span = (AbstractSpan) context.getContext(); + span.log(t); + } +} +``` + +**Key V2 classes:** +- `ClassEnhancePluginDefineV2` - Base class for plugins with both instance and static methods +- `ClassInstanceMethodsEnhancePluginDefineV2` - For instance methods only +- `ClassStaticMethodsEnhancePluginDefineV2` - For static methods only +- `InstanceMethodsAroundInterceptorV2` - Interceptor interface with `MethodInvocationContext` +- `StaticMethodsAroundInterceptorV2` - Static method interceptor with context + +### V1 API (Legacy) + +V1 uses `MethodInterceptResult` only in `beforeMethod` and has no shared context between phases. **Only use for maintaining existing legacy plugins.** + +**Key V1 classes (legacy):** +- `ClassEnhancePluginDefine` +- `ClassInstanceMethodsEnhancePluginDefine` +- `ClassStaticMethodsEnhancePluginDefine` +- `InstanceMethodsAroundInterceptor` +- `StaticMethodsAroundInterceptor` + +## Plugin Development Rules + +### Class Matching Restrictions + +**CRITICAL: Never use `.class` references in instrumentation definitions:** +```java +// WRONG - will break the agent if ThirdPartyClass doesn't exist +takesArguments(ThirdPartyClass.class) +byName(ThirdPartyClass.class.getName()) + +// CORRECT - use string literals +takesArguments("com.example.ThirdPartyClass") +byName("com.example.ThirdPartyClass") +``` + +**ClassMatch options:** +- `byName(String)`: Match by full class name (package + class name) - **preferred** +- `byClassAnnotationMatch`: Match classes with specific annotations (does NOT support inherited annotations) +- `byMethodAnnotationMatch`: Match classes with methods having specific annotations +- `byHierarchyMatch`: Match by parent class/interface - **avoid unless necessary** (performance impact) + +### Witness Classes/Methods + +Use witness classes/methods to activate plugins only for specific library versions: +```java +@Override +protected String[] witnessClasses() { + return new String[] { "com.example.VersionSpecificClass" }; +} + +@Override +protected List witnessMethods() { + return Collections.singletonList( + new WitnessMethod("com.example.SomeClass", ElementMatchers.named("specificMethod")) + ); +} +``` + +### Plugin Configuration + +Use `@PluginConfig` annotation for custom plugin settings: +```java +public class MyPluginConfig { + public static class Plugin { + @PluginConfig(root = MyPluginConfig.class) + public static class MyPlugin { + public static boolean SOME_SETTING = false; + } + } +} +``` +Config key becomes: `plugin.myplugin.some_setting` + +### Dependency Management + +**Plugin dependencies must use `provided` scope:** +```xml + + com.example + target-library + ${version} + provided + +``` + +**Agent core dependency policy:** +- New dependencies in agent core are treated with extreme caution +- Prefer using existing imported libraries already in the project +- Prefer JDK standard libraries over third-party libraries +- Plugins should rely on the target application's libraries (provided scope), not bundle them + +## Tracing Concepts + +### Span Types +- **EntrySpan**: Service provider/endpoint (HTTP server, MQ consumer) +- **LocalSpan**: Internal method (no remote calls) +- **ExitSpan**: Client call (HTTP client, DB access, MQ producer) + +### SpanLayer (required for EntrySpan/ExitSpan) +- `DB`: Database access +- `RPC_FRAMEWORK`: RPC calls (not ordinary HTTP) +- `HTTP`: HTTP calls +- `MQ`: Message queue +- `UNKNOWN`: Default + +### Context Propagation +- **ContextCarrier**: Cross-process propagation (serialize to headers/attachments) +- **ContextSnapshot**: Cross-thread propagation (in-memory, no serialization) + +### Required Span Attributes +For EntrySpan and ExitSpan, always set: +```java +span.setComponent(ComponentsDefine.YOUR_COMPONENT); +span.setLayer(SpanLayer.HTTP); // or DB, MQ, RPC_FRAMEWORK +``` + +### Special Tags for OAP Analysis +| Tag | Purpose | +|-----|---------| +| `http.status_code` | HTTP response code (integer) | +| `db.type` | Database type (e.g., "sql", "redis") | +| `db.statement` | SQL/query statement (enables slow query analysis) | +| `cache.type`, `cache.op`, `cache.cmd`, `cache.key` | Cache metrics | +| `mq.queue`, `mq.topic` | MQ metrics | + +## Meter Plugin APIs + +For collecting numeric metrics (alternative to tracing): +```java +// Counter +Counter counter = MeterFactory.counter("metric_name") + .tag("key", "value") + .mode(Counter.Mode.INCREMENT) + .build(); +counter.increment(1d); + +// Gauge +Gauge gauge = MeterFactory.gauge("metric_name", () -> getValue()) + .tag("key", "value") + .build(); + +// Histogram +Histogram histogram = MeterFactory.histogram("metric_name") + .steps(Arrays.asList(1, 5, 10)) + .build(); +histogram.addValue(3); +``` + +## Adding a New SDK Plugin + +1. Create directory: `apm-sniffer/apm-sdk-plugin/{framework}-{version}-plugin/` +2. Implement instrumentation class using **V2 API** (extend `ClassInstanceMethodsEnhancePluginDefineV2`) +3. Implement interceptor class using **V2 API** (implement `InstanceMethodsAroundInterceptorV2`) +4. Register plugin in `skywalking-plugin.def` file +5. Add test scenario in `test/plugin/scenarios/` + +## Plugin Test Framework + +The plugin test framework verifies plugin functionality using Docker containers with real services and a mock OAP backend. + +### Environment Requirements +- MacOS/Linux +- JDK 8+ +- Docker & Docker Compose + +### Test Case Structure + +**JVM-container (preferred):** +``` +{scenario}-scenario/ +├── bin/ +│ └── startup.sh # JVM startup script (required) +├── config/ +│ └── expectedData.yaml # Expected trace/meter/log data +├── src/main/java/... # Test application code +├── pom.xml +├── configuration.yml # Test case configuration +└── support-version.list # Supported versions (one per line) +``` + +**Tomcat-container:** +``` +{scenario}-scenario/ +├── config/ +│ └── expectedData.yaml +├── src/main/ +│ ├── java/... +│ └── webapp/WEB-INF/web.xml +├── pom.xml +├── configuration.yml +└── support-version.list +``` + +### Key Configuration Files + +**configuration.yml:** +```yaml +type: jvm # or tomcat +entryService: http://localhost:8080/case # Entry endpoint (GET) +healthCheck: http://localhost:8080/health # Health check endpoint (HEAD) +startScript: ./bin/startup.sh # JVM-container only +runningMode: default # default|with_optional|with_bootstrap +withPlugins: apm-spring-annotation-plugin-*.jar # For optional/bootstrap modes +environment: + - KEY=value +dependencies: # External services (docker-compose style) + mysql: + image: mysql:8.0 + hostname: mysql + environment: + - MYSQL_ROOT_PASSWORD=root +``` + +**support-version.list:** +``` +# One version per line, use # for comments +# Only include ONE version per minor version (not all patch versions) +4.3.6 +4.4.1 +4.5.0 +``` + +**expectedData.yaml:** + +Trace and meter expectations are typically in separate scenarios. + +*For tracing plugins:* +```yaml +segmentItems: + - serviceName: your-scenario + segmentSize: ge 1 # Operators: eq, ge, gt, nq + segments: + - segmentId: not null + spans: + - operationName: /your/endpoint + parentSpanId: -1 # -1 for root span + spanId: 0 + spanLayer: Http # Http, DB, RPC_FRAMEWORK, MQ, CACHE, Unknown + spanType: Entry # Entry, Exit, Local + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + peer: '' # Empty string for Entry/Local, required for Exit + skipAnalysis: false + tags: + - {key: url, value: not null} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + logs: [] + refs: [] # SegmentRefs for cross-process/cross-thread +``` + +*For meter plugins:* +```yaml +meterItems: + - serviceName: your-scenario + meterSize: ge 1 + meters: + - meterId: + name: test_counter + tags: + - {name: key1, value: value1} # Note: uses 'name' not 'key' + singleValue: gt 0 # For counter/gauge + - meterId: + name: test_histogram + tags: + - {name: key1, value: value1} + histogramBuckets: # For histogram + - 0.0 + - 1.0 + - 5.0 + - 10.0 +``` + +**startup.sh (JVM-container):** +```bash +#!/bin/bash +home="$(cd "$(dirname $0)"; pwd)" +# ${agent_opts} is REQUIRED - contains agent parameters +java -jar ${agent_opts} ${home}/../libs/your-scenario.jar & +``` + +### Running Plugin Tests Locally + +```bash +# Run a specific scenario +bash ./test/plugin/run.sh -f {scenario_name} + +# IMPORTANT: Rebuild agent if apm-sniffer code changed +./mvnw clean package -DskipTests -pl apm-sniffer + +# Use generator to create new test case +bash ./test/plugin/generator.sh +``` + +### Adding Tests to CI + +Add scenario to the appropriate `.github/workflows/` file: +- Use `python3 tools/select-group.py` to find the file with fewest cases +- **JDK 8 tests**: `plugins-test..yaml` +- **JDK 17 tests**: `plugins-jdk17-test..yaml` +- **JDK 21 tests**: `plugins-jdk21-test..yaml` +- **JDK 25 tests**: `plugins-jdk25-test..yaml` + +```yaml +matrix: + case: + - your-scenario-scenario +``` + +### Test Code Package Naming +- Test code: `org.apache.skywalking.apm.testcase.*` +- Code to be instrumented: `test.org.apache.skywalking.apm.testcase.*` + +## Tips for AI Assistants + +1. **Use V2 instrumentation API**: Always use V2 classes for new plugins; V1 is legacy +2. **NEVER use `.class` references**: Always use string literals for class names +3. **Always set component and layer**: For EntrySpan and ExitSpan, always call `setComponent()` and `setLayer()` +4. **Prefer `byName` for class matching**: Avoid `byHierarchyMatch` unless necessary (performance impact) +5. **Use witness classes for version-specific plugins**: Implement `witnessClasses()` or `witnessMethods()` +6. **Follow plugin patterns**: Use existing V2 plugins as templates +7. **Plugin naming**: Follow `{framework}-{version}-plugin` convention +8. **Register plugins**: Always add plugin definition to `skywalking-plugin.def` file +9. **Java version compatibility**: Agent core must maintain Java 8 compatibility, but individual plugins may target higher JDK versions +10. **Shaded dependencies**: Core dependencies are shaded to avoid classpath conflicts diff --git a/apm-sniffer/bootstrap-plugins/CLAUDE.md b/apm-sniffer/bootstrap-plugins/CLAUDE.md new file mode 100644 index 0000000000..51b4db99e7 --- /dev/null +++ b/apm-sniffer/bootstrap-plugins/CLAUDE.md @@ -0,0 +1,53 @@ +# CLAUDE.md - Bootstrap Plugin Development Guide + +This guide covers developing bootstrap-level plugins in `apm-sniffer/bootstrap-plugins/`. + +For general plugin development concepts (V2 API, tracing, class matching, testing), see `apm-sniffer/apm-sdk-plugin/CLAUDE.md`. + +## What Are Bootstrap Plugins? + +Bootstrap plugins instrument JDK core classes (rt.jar / java.base module) at the JVM bootstrap phase. They are loaded before application classes and can intercept fundamental JDK APIs. + +**Examples:** +- `jdk-threading-plugin` - Thread pool context propagation +- `jdk-http-plugin` - `HttpURLConnection` instrumentation +- `jdk-httpclient-plugin` - JDK 11+ `HttpClient` instrumentation +- `jdk-virtual-thread-executor-plugin` - JDK 21+ virtual thread support +- `jdk-forkjoinpool-plugin` - `ForkJoinPool` instrumentation + +## Key Difference from SDK Plugins + +Bootstrap plugins **must** override `isBootstrapInstrumentation()`: +```java +@Override +public boolean isBootstrapInstrumentation() { + return true; +} +``` + +**WARNING**: Use bootstrap instrumentation only where absolutely necessary. It affects JDK core classes and has broader impact than SDK plugins. + +## Development Rules + +All general plugin development rules apply (see `apm-sdk-plugin/CLAUDE.md`), plus: + +1. **Use V2 API** for new bootstrap plugins, same as SDK plugins +2. **Minimal scope**: Only intercept what is strictly necessary in JDK classes +3. **Performance critical**: Bootstrap plugins run on core JDK paths - keep interceptor logic lightweight +4. **Class loading awareness**: JDK core classes are loaded by the bootstrap classloader; be careful with class references that might not be visible at bootstrap level + +## Testing Bootstrap Plugins + +Bootstrap plugin test scenarios use `runningMode: with_bootstrap` in `configuration.yml`: +```yaml +type: jvm +entryService: http://localhost:8080/case +healthCheck: http://localhost:8080/health +startScript: ./bin/startup.sh +runningMode: with_bootstrap +withPlugins: jdk-threading-plugin-*.jar +``` + +This tells the test framework to load the plugin at the bootstrap level instead of the normal plugin directory. + +See `apm-sdk-plugin/CLAUDE.md` for full test framework documentation. From b03d63c8babcface3498344bf5feb1be2883393d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Sat, 21 Feb 2026 19:18:46 +0800 Subject: [PATCH 090/114] Begin 9.7.0 iteration, 9.6.0 is tagged for release. (#791) --- .github/actions/build/action.yml | 1 + .github/actions/run/action.yml | 19 +++- .github/workflows/e2e.yaml | 2 +- .github/workflows/plugins-jdk11-test.3.yaml | 15 ++++ .github/workflows/plugins-jdk17-test.0.yaml | 15 ++++ .github/workflows/plugins-jdk17-test.1.yaml | 15 ++++ .github/workflows/plugins-jdk21-test.0.yaml | 15 ++++ .github/workflows/plugins-jdk25-test.0.yaml | 15 ++++ .github/workflows/plugins-test.0.yaml | 15 ++++ .github/workflows/plugins-test.1.yaml | 15 ++++ .github/workflows/plugins-test.2.yaml | 17 +++- .github/workflows/plugins-test.3.yaml | 15 ++++ .../workflows/plugins-tomcat10-test.0.yaml | 15 ++++ .github/workflows/plugins-tomcat9-test.0.yaml | 15 ++++ .github/workflows/publish-docker.yaml | 15 ++++ CHANGES.md | 29 +----- .../apm-toolkit-kafka/pom.xml | 2 +- .../apm-toolkit-log4j-1.x/pom.xml | 2 +- .../apm-toolkit-log4j-2.x/pom.xml | 2 +- .../apm-toolkit-logback-1.x/pom.xml | 2 +- .../apm-toolkit-meter/pom.xml | 2 +- .../apm-toolkit-micrometer-1.10/pom.xml | 2 +- .../apm-toolkit-micrometer-registry/pom.xml | 2 +- .../apm-toolkit-opentracing/pom.xml | 2 +- .../apm-toolkit-trace/pom.xml | 2 +- .../apm-toolkit-webflux/pom.xml | 2 +- apm-application-toolkit/pom.xml | 2 +- apm-commons/apm-datacarrier/pom.xml | 2 +- apm-commons/apm-util/pom.xml | 2 +- apm-commons/pom.xml | 2 +- apm-protocol/apm-network/pom.xml | 2 +- apm-protocol/pom.xml | 2 +- apm-sniffer/apm-agent-core/pom.xml | 2 +- apm-sniffer/apm-agent/pom.xml | 2 +- .../activemq-5.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/aerospike-plugin/pom.xml | 2 +- .../apm-armeria-0.84.x-plugin/pom.xml | 2 +- .../apm-armeria-0.85.x-plugin/pom.xml | 2 +- .../apm-armeria-1.0.x-plugin/pom.xml | 2 +- .../apm-armeria-plugins/pom.xml | 2 +- .../asynchttpclient-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/avro-plugin/pom.xml | 2 +- .../baidu-brpc-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/baidu-brpc-plugin/pom.xml | 2 +- .../apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/canal-1.x-plugin/pom.xml | 2 +- .../cassandra-java-driver-3.x-plugin/pom.xml | 2 +- .../clickhouse-0.3.1-plugin/pom.xml | 2 +- .../clickhouse-0.3.2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/cxf-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/dbcp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/druid-1.x-plugin/pom.xml | 2 +- .../dubbo-2.7.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml | 2 +- .../dubbo-3.x-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-3.x-plugin/pom.xml | 2 +- .../dubbo-conflict-patch/pom.xml | 2 +- .../apm-sdk-plugin/dubbo-plugin/pom.xml | 2 +- .../elastic-job-2.x-plugin/pom.xml | 2 +- .../elasticjob-3.x-plugin/pom.xml | 2 +- .../elasticsearch-5.x-plugin/pom.xml | 2 +- .../elasticsearch-6.x-plugin/pom.xml | 2 +- .../elasticsearch-7.x-plugin/pom.xml | 2 +- .../elasticsearch-common/pom.xml | 2 +- .../feign-default-http-9.x-plugin/pom.xml | 2 +- .../finagle-6.25.x-plugin/pom.xml | 2 +- .../graphql-12.x-15.x-plugin/pom.xml | 2 +- .../graphql-16plus-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-8.x-plugin/pom.xml | 2 +- .../graphql-plugin/graphql-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/graphql-plugin/pom.xml | 2 +- .../grizzly-2.3.x-4.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/grpc-1.x-plugin/pom.xml | 2 +- .../guava-eventbus-plugin/pom.xml | 2 +- .../apm-sdk-plugin/h2-1.x-plugin/pom.xml | 2 +- .../hbase-1.x-2.x-plugin/pom.xml | 2 +- .../hikaricp-3.x-4.x-plugin/pom.xml | 2 +- .../httpClient-4.x-plugin/pom.xml | 2 +- .../httpasyncclient-4.x-plugin/pom.xml | 2 +- .../httpclient-3.x-plugin/pom.xml | 2 +- .../httpclient-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/httpclient-commons/pom.xml | 2 +- .../hutool-http-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/hutool-plugins/pom.xml | 2 +- .../apm-sdk-plugin/hystrix-1.x-plugin/pom.xml | 2 +- .../influxdb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jdbc-commons/pom.xml | 2 +- .../jedis-2.x-3.x-plugin/pom.xml | 2 +- .../jedis-plugins/jedis-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jedis-plugins/pom.xml | 2 +- .../apm-sdk-plugin/jersey-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jersey-3.x-plugin/pom.xml | 2 +- .../jetty-client-11.x-plugin/pom.xml | 2 +- .../jetty-client-9.0-plugin/pom.xml | 2 +- .../jetty-client-9.x-plugin/pom.xml | 2 +- .../jetty-server-11.x-plugin/pom.xml | 2 +- .../jetty-server-9.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/jetty-plugin/pom.xml | 2 +- .../jetty-thread-pool-plugin/pom.xml | 2 +- .../jsonrpc4j-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/kafka-commons/pom.xml | 2 +- .../apm-sdk-plugin/kafka-plugin/pom.xml | 2 +- .../kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml | 2 +- .../lettuce-5.x-6.4.x-plugin/pom.xml | 2 +- .../lettuce-6.5.x-plugin/pom.xml | 2 +- .../lettuce-plugins/lettuce-common/pom.xml | 2 +- .../apm-sdk-plugin/lettuce-plugins/pom.xml | 2 +- .../light4j-plugins/light4j-plugin/pom.xml | 2 +- .../apm-sdk-plugin/light4j-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mariadb-2.x-plugin/pom.xml | 2 +- .../micronaut-http-client-plugin/pom.xml | 2 +- .../micronaut-http-server-plugin/pom.xml | 2 +- .../apm-sdk-plugin/micronaut-plugins/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mongodb-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/motan-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mssql-commons/pom.xml | 2 +- .../apm-sdk-plugin/mssql-jdbc-plugin/pom.xml | 2 +- .../mssql-jtds-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-6.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/mysql-common/pom.xml | 2 +- .../nats-2.14.x-2.16.5-plugin/pom.xml | 2 +- .../apm-sdk-plugin/neo4j-4.x-plugin/pom.xml | 2 +- .../netty-socketio-plugin/pom.xml | 2 +- .../nutz-plugins/http-1.x-plugin/pom.xml | 2 +- .../mvc-annotation-1.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/nutz-plugins/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-4.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/okhttp-common/pom.xml | 2 +- .../apm-sdk-plugin/play-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-sdk-plugin/pom.xml | 2 +- .../postgresql-8.x-plugin/pom.xml | 2 +- .../pulsar-2.2-2.7-plugin/pom.xml | 2 +- .../pulsar-2.8.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/pulsar-common/pom.xml | 2 +- .../apm-sdk-plugin/quasar-plugin/pom.xml | 2 +- .../apm-sdk-plugin/rabbitmq-plugin/pom.xml | 2 +- .../redisson-3.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/resteasy-plugin/pom.xml | 2 +- .../resteasy-server-3.x-plugin/pom.xml | 2 +- .../resteasy-server-4.x-plugin/pom.xml | 2 +- .../resteasy-server-6.x-plugin/pom.xml | 2 +- .../rocketMQ-3.x-plugin/pom.xml | 2 +- .../rocketMQ-4.x-plugin/pom.xml | 2 +- .../rocketMQ-5.x-plugin/pom.xml | 2 +- .../rocketMQ-client-java-5.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/servicecomb-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../shardingsphere-plugins/pom.xml | 2 +- .../sharding-sphere-3.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.0.x-plugin/pom.xml | 2 +- .../sharding-sphere-4.1.0-plugin/pom.xml | 2 +- .../sharding-sphere-5.0.0-plugin/pom.xml | 2 +- .../apm-sdk-plugin/sofarpc-plugin/pom.xml | 2 +- .../sofarpc/InvokeCallbackWrapperTest.java | 11 ++- .../apm-sdk-plugin/solon-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/solrj-7.x-plugin/pom.xml | 2 +- .../async-annotation-plugin/pom.xml | 2 +- .../concurrent-util-4.x-plugin/pom.xml | 2 +- .../spring-plugins/core-patch/pom.xml | 2 +- .../mvc-annotation-3.x-plugin/pom.xml | 2 +- .../mvc-annotation-4.x-plugin/pom.xml | 2 +- .../mvc-annotation-5.x-plugin/pom.xml | 2 +- .../mvc-annotation-commons/pom.xml | 2 +- .../apm-sdk-plugin/spring-plugins/pom.xml | 2 +- .../resttemplate-3.x-plugin/pom.xml | 2 +- .../resttemplate-4.x-plugin/pom.xml | 2 +- .../resttemplate-commons/pom.xml | 2 +- .../scheduled-annotation-plugin/pom.xml | 2 +- .../spring-cloud/netflix-plugins/pom.xml | 2 +- .../spring-cloud-feign-1.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-cloud/pom.xml | 2 +- .../spring-cloud-feign-2.x-plugin/pom.xml | 2 +- .../spring-plugins/spring-commons/pom.xml | 2 +- .../spring-kafka-1.x-plugin/pom.xml | 2 +- .../spring-kafka-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../pom.xml | 2 +- .../spymemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/struts2-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/thrift-plugin/pom.xml | 2 +- .../apm-sdk-plugin/tomcat-10x-plugin/pom.xml | 2 +- .../tomcat-7.x-8.x-plugin/pom.xml | 2 +- .../tomcat-thread-pool-plugin/pom.xml | 2 +- .../apm-sdk-plugin/undertow-plugins/pom.xml | 2 +- .../undertow-2.x-plugin/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-sdk-plugin/vertx-plugins/pom.xml | 2 +- .../vertx-core-3.x-plugin/pom.xml | 2 +- .../vertx-core-4.x-plugin/pom.xml | 2 +- .../websphere-liberty-23.x-plugin/pom.xml | 2 +- .../xmemcached-2.x-plugin/pom.xml | 2 +- .../apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml | 2 +- apm-sniffer/apm-test-tools/pom.xml | 2 +- .../apm-toolkit-kafka-activation/pom.xml | 2 +- .../apm-toolkit-log4j-1.x-activation/pom.xml | 2 +- .../apm-toolkit-log4j-2.x-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-logging-common/pom.xml | 2 +- .../apm-toolkit-meter-activation/pom.xml | 2 +- .../apm-toolkit-micrometer-activation/pom.xml | 2 +- .../pom.xml | 2 +- .../apm-toolkit-trace-activation/pom.xml | 2 +- .../apm-toolkit-webflux-activation/pom.xml | 2 +- apm-sniffer/apm-toolkit-activation/pom.xml | 2 +- .../jdk-forkjoinpool-plugin/pom.xml | 2 +- .../bootstrap-plugins/jdk-http-plugin/pom.xml | 4 +- .../jdk-httpclient-plugin/pom.xml | 2 +- .../jdk-threading-plugin/pom.xml | 2 +- .../jdk-threadpool-plugin/pom.xml | 2 +- .../pom.xml | 2 +- apm-sniffer/bootstrap-plugins/pom.xml | 2 +- apm-sniffer/bytebuddy-patch/pom.xml | 2 +- .../impala-jdbc-2.6.x-plugin/pom.xml | 2 +- apm-sniffer/expired-plugins/pom.xml | 2 +- .../caffeine-3.x-plugin/pom.xml | 2 +- .../customize-enhance-plugin/pom.xml | 2 +- .../ehcache-2.x-plugin/pom.xml | 2 +- .../fastjson-1.2.x-plugin/pom.xml | 2 +- .../gson-2.8.x-plugin/pom.xml | 2 +- .../guava-cache-plugin/pom.xml | 2 +- .../jackson-2.x-plugin/pom.xml | 2 +- .../kotlin-coroutine-plugin/pom.xml | 2 +- .../mybatis-3.x-plugin/pom.xml | 2 +- .../nacos-client-2.x-plugin/pom.xml | 2 +- .../netty-http-4.1.x-plugin/pom.xml | 2 +- .../mvc-annotation-6.x-plugin/pom.xml | 2 +- .../gateway-2.0.x-plugin/pom.xml | 2 +- .../gateway-2.1.x-plugin/pom.xml | 2 +- .../gateway-3.x-plugin/pom.xml | 2 +- .../gateway-4.x-plugin/pom.xml | 2 +- .../optional-spring-cloud/pom.xml | 2 +- .../optional-spring-plugins/pom.xml | 2 +- .../resttemplate-6.x-plugin/pom.xml | 2 +- .../spring-annotation-plugin/pom.xml | 2 +- .../spring-tx-plugin/pom.xml | 2 +- .../spring-webflux-5.x-plugin/pom.xml | 2 +- .../spring-webflux-6.x-plugin/pom.xml | 2 +- apm-sniffer/optional-plugins/pom.xml | 2 +- .../quartz-scheduler-2.x-plugin/pom.xml | 2 +- .../sentinel-1.x-plugin/pom.xml | 2 +- .../shenyu-2.4.x-plugin/pom.xml | 2 +- .../trace-ignore-plugin/pom.xml | 2 +- .../trace-sampler-cpu-policy-plugin/pom.xml | 2 +- .../zookeeper-3.4.x-plugin/pom.xml | 2 +- .../kafka-config-extension/pom.xml | 2 +- .../kafka-reporter-plugin/pom.xml | 2 +- apm-sniffer/optional-reporter-plugins/pom.xml | 2 +- apm-sniffer/pom.xml | 2 +- changes/changes-9.6.0.md | 33 +++++++ pom.xml | 2 +- .../jvm-container/src/main/docker/run.sh | 7 +- .../resources/compose-start-script.template | 35 +++++++- .../resources/container-start-script.template | 16 +++- .../configuration.yml | 5 +- .../support-version.list | 1 - .../configuration.yml | 2 +- .../rocketmq-5-grpc-scenario/pom.xml | 2 +- .../java/controller/CaseController.java | 72 ++++++++++----- .../java/controller/MessageService.java | 18 ++-- .../src/main/resources/log4j2.xml | 2 +- .../support-version.list | 1 - .../rocketmq/controller/CaseController.java | 90 ++++++++++++------- .../src/main/resources/log4j2.xml | 2 +- .../rocketmq-scenario/support-version.list | 2 +- 272 files changed, 663 insertions(+), 351 deletions(-) create mode 100644 changes/changes-9.6.0.md diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index a41636ac28..80e4344366 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -88,6 +88,7 @@ runs: mkdir -p test-containers docker save -o test-containers/skywalking-agent-test-jvm-1.0.0.tgz skywalking/agent-test-jvm:1.0.0 docker save -o test-containers/skywalking-agent-test-tomcat-1.0.0.tgz skywalking/agent-test-tomcat:1.0.0 + ls -la test-containers/ echo "::endgroup::" - uses: actions/upload-artifact@v4 name: Upload Test Containers diff --git a/.github/actions/run/action.yml b/.github/actions/run/action.yml index 75a7ee9c26..bb9b3c6143 100644 --- a/.github/actions/run/action.yml +++ b/.github/actions/run/action.yml @@ -32,6 +32,22 @@ runs: - uses: actions/download-artifact@v4 with: name: test-tools + - name: Disable containerd image store + shell: bash + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Load Test Containers shell: bash run: | @@ -41,6 +57,7 @@ runs: if ls test-containers/skywalking-agent-test-tomcat-1.0.0.tgz; then docker load -i test-containers/skywalking-agent-test-tomcat-1.0.0.tgz fi + docker images - name: Cache local Maven repository uses: actions/cache@v4 with: @@ -51,7 +68,7 @@ runs: shell: bash run: | echo "::group::Run Plugin Test ${{ inputs.test_case }}" - bash test/plugin/run.sh ${{ inputs.test_case }} + bash test/plugin/run.sh --debug ${{ inputs.test_case }} echo "::endgroup::" - uses: actions/upload-artifact@v4 name: Upload Agent diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index dc595bc85c..a2393b4942 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -60,7 +60,7 @@ jobs: with: go-version: '1.24' - name: Run E2E Tests - uses: apache/skywalking-infra-e2e@7e4b5b68716fdb7b79b21fa8908f9db497e1b115 + uses: apache/skywalking-infra-e2e@8c21e43e241a32a54bdf8eeceb9099eb27e5e9b4 with: e2e-file: ${{ matrix.case.path }} - uses: actions/upload-artifact@v4 diff --git a/.github/workflows/plugins-jdk11-test.3.yaml b/.github/workflows/plugins-jdk11-test.3.yaml index 0e1fe2f74b..238fd4047c 100644 --- a/.github/workflows/plugins-jdk11-test.3.yaml +++ b/.github/workflows/plugins-jdk11-test.3.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build with: diff --git a/.github/workflows/plugins-jdk17-test.0.yaml b/.github/workflows/plugins-jdk17-test.0.yaml index 6d2ad4c2b6..cfec09ac3c 100644 --- a/.github/workflows/plugins-jdk17-test.0.yaml +++ b/.github/workflows/plugins-jdk17-test.0.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build with: diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index 418da87f35..0aa6266813 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build with: diff --git a/.github/workflows/plugins-jdk21-test.0.yaml b/.github/workflows/plugins-jdk21-test.0.yaml index 87b058284c..9e6805515f 100644 --- a/.github/workflows/plugins-jdk21-test.0.yaml +++ b/.github/workflows/plugins-jdk21-test.0.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build with: diff --git a/.github/workflows/plugins-jdk25-test.0.yaml b/.github/workflows/plugins-jdk25-test.0.yaml index 88c7213101..06526df29f 100644 --- a/.github/workflows/plugins-jdk25-test.0.yaml +++ b/.github/workflows/plugins-jdk25-test.0.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build local tomcat-curl image run: | docker build -t tomcat-curl:10.1.50-jdk25-temurin \ diff --git a/.github/workflows/plugins-test.0.yaml b/.github/workflows/plugins-test.0.yaml index a3f2653a1e..0c86b2e8ad 100644 --- a/.github/workflows/plugins-test.0.yaml +++ b/.github/workflows/plugins-test.0.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build diff --git a/.github/workflows/plugins-test.1.yaml b/.github/workflows/plugins-test.1.yaml index 2c012792fc..5b67f1d22d 100644 --- a/.github/workflows/plugins-test.1.yaml +++ b/.github/workflows/plugins-test.1.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build diff --git a/.github/workflows/plugins-test.2.yaml b/.github/workflows/plugins-test.2.yaml index ccb6a7865d..5fe28c244f 100644 --- a/.github/workflows/plugins-test.2.yaml +++ b/.github/workflows/plugins-test.2.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build @@ -76,11 +91,11 @@ jobs: - struts2.5-scenario - cxf-scenario - okhttp2-scenario - - rocketmq-scenario - jersey-2.0.x-2.25.x-scenario - jersey-2.26.x-2.39.x-scenario - websphere-liberty-23.x-scenario - nacos-client-2.x-scenario + - rocketmq-scenario - rocketmq-5-grpc-scenario steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index b6766b15a0..3d5880fd9f 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build diff --git a/.github/workflows/plugins-tomcat10-test.0.yaml b/.github/workflows/plugins-tomcat10-test.0.yaml index 6ba26a754c..9bac4133d9 100644 --- a/.github/workflows/plugins-tomcat10-test.0.yaml +++ b/.github/workflows/plugins-tomcat10-test.0.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build with: diff --git a/.github/workflows/plugins-tomcat9-test.0.yaml b/.github/workflows/plugins-tomcat9-test.0.yaml index 8f54080254..400e8a0ff6 100644 --- a/.github/workflows/plugins-tomcat9-test.0.yaml +++ b/.github/workflows/plugins-tomcat9-test.0.yaml @@ -41,6 +41,21 @@ jobs: - uses: actions/checkout@v2 with: submodules: true + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Build uses: ./.github/actions/build with: diff --git a/.github/workflows/publish-docker.yaml b/.github/workflows/publish-docker.yaml index 7c1f4726b5..1eb75de778 100644 --- a/.github/workflows/publish-docker.yaml +++ b/.github/workflows/publish-docker.yaml @@ -75,6 +75,21 @@ jobs: with: name: skywalking-agent path: skywalking-agent + - name: Disable containerd image store + run: | + DAEMON_JSON="/etc/docker/daemon.json" + if [ -f "$DAEMON_JSON" ]; then + sudo jq '. + {"features": {"containerd-snapshotter": false}}' "$DAEMON_JSON" \ + | sudo tee "${DAEMON_JSON}.tmp" > /dev/null + sudo mv "${DAEMON_JSON}.tmp" "$DAEMON_JSON" + else + echo '{"features": {"containerd-snapshotter": false}}' \ + | sudo tee "$DAEMON_JSON" > /dev/null + fi + sudo systemctl restart docker + docker version + docker info + echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Log in to the Container registry uses: docker/login-action@v1.10.0 with: diff --git a/CHANGES.md b/CHANGES.md index 979502ce7a..eaa28ff2c8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,35 +2,12 @@ Changes by Version ================== Release Notes. -9.6.0 +9.7.0 ------------------ -* Add CLAUDE.md for AI assistant guidance. -* Bump up agent-oap protocol to latest(16c51358ebcf42629bf4ffdf952253971f20eb25). -* Bump up gRPC to v1.74.0. -* Bump up netty to v4.1.124.Final. -* Bump up GSON to v2.13.1. -* Bump up guava to v32.1.3. -* Bump up oap to the 10.3-dev.latest(dc8740d4757b35374283c4850a9a080e40f0eb79) in e2e. -* Bump up cli to the 0.15.0-dev.latest(77b4c49e89c9c000278f44e62729d534f2ec842e) in e2e. -* Bump up apache parent pom to v35. -* Update Maven to 3.6.3 in mvnw. -* Fix OOM due to too many span logs. -* Fix ClassLoader cache OOM issue with WeakHashMap. -* Fix Jetty client cannot receive the HTTP response body. -* Eliminate repeated code with HttpServletRequestWrapper in mvc-annotation-commons. -* Add the jdk httpclient plugin. -* Fix Gateway 2.0.x plugin not activated for spring-cloud-starter-gateway 2.0.0.RELEASE. -* Support kafka-clients-3.9.x intercept. -* Upgrade kafka-clients version in optional-reporter-plugins to 3.9.1. -* Fix AbstractLogger replaceParam when the replaced string contains a replacement marker. -* Fix `JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH` was not working in some plugins. -* Bump up Lombok to v1.18.42 to adopt JDK25 compiling. -* Add `eclipse-temurin:25-jre` as another base image. -* Add JDK25 plugin tests for Spring 6. -* Ignore classes starting with "sun.nio.cs" in bytebuddy due to potential class loading deadlock. -All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) ------------------ Find change logs of all versions [here](changes). diff --git a/apm-application-toolkit/apm-toolkit-kafka/pom.xml b/apm-application-toolkit/apm-toolkit-kafka/pom.xml index 05365ce572..695985162e 100644 --- a/apm-application-toolkit/apm-toolkit-kafka/pom.xml +++ b/apm-application-toolkit/apm-toolkit-kafka/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml index e2b12f7171..6983c0d2e9 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml index 3b0ecb2103..393ea94496 100644 --- a/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-log4j-2.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml index f7f441bde3..f5b9d63625 100644 --- a/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml +++ b/apm-application-toolkit/apm-toolkit-logback-1.x/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-meter/pom.xml b/apm-application-toolkit/apm-toolkit-meter/pom.xml index b5d212c20c..9c2af46e51 100644 --- a/apm-application-toolkit/apm-toolkit-meter/pom.xml +++ b/apm-application-toolkit/apm-toolkit-meter/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml index b570a7fda8..70e3a957d6 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-1.10/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml index 8c972efdc2..5658bea135 100644 --- a/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml +++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml index 5d0dc02d38..a7d9aefd2a 100644 --- a/apm-application-toolkit/apm-toolkit-opentracing/pom.xml +++ b/apm-application-toolkit/apm-toolkit-opentracing/pom.xml @@ -21,7 +21,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-trace/pom.xml b/apm-application-toolkit/apm-toolkit-trace/pom.xml index 5b186af0d9..642a551645 100644 --- a/apm-application-toolkit/apm-toolkit-trace/pom.xml +++ b/apm-application-toolkit/apm-toolkit-trace/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/apm-toolkit-webflux/pom.xml b/apm-application-toolkit/apm-toolkit-webflux/pom.xml index 2dab4fc7ea..8397b9193f 100644 --- a/apm-application-toolkit/apm-toolkit-webflux/pom.xml +++ b/apm-application-toolkit/apm-toolkit-webflux/pom.xml @@ -20,7 +20,7 @@ apm-application-toolkit org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-application-toolkit/pom.xml b/apm-application-toolkit/pom.xml index e004d63b06..cc173543d0 100644 --- a/apm-application-toolkit/pom.xml +++ b/apm-application-toolkit/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 apm-application-toolkit diff --git a/apm-commons/apm-datacarrier/pom.xml b/apm-commons/apm-datacarrier/pom.xml index fd0cbf6280..a3c91d10ba 100644 --- a/apm-commons/apm-datacarrier/pom.xml +++ b/apm-commons/apm-datacarrier/pom.xml @@ -21,7 +21,7 @@ java-agent-commons org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/apm-util/pom.xml b/apm-commons/apm-util/pom.xml index bf1169bfde..1bbb7009a4 100644 --- a/apm-commons/apm-util/pom.xml +++ b/apm-commons/apm-util/pom.xml @@ -20,7 +20,7 @@ java-agent-commons org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-commons/pom.xml b/apm-commons/pom.xml index 3b54179ebe..79e66796ca 100644 --- a/apm-commons/pom.xml +++ b/apm-commons/pom.xml @@ -20,7 +20,7 @@ java-agent org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/apm-network/pom.xml b/apm-protocol/apm-network/pom.xml index 9964486b65..a1531c3ca0 100644 --- a/apm-protocol/apm-network/pom.xml +++ b/apm-protocol/apm-network/pom.xml @@ -21,7 +21,7 @@ java-agent-protocol org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-protocol/pom.xml b/apm-protocol/pom.xml index 10be0c6791..3cfb939955 100644 --- a/apm-protocol/pom.xml +++ b/apm-protocol/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-agent-core/pom.xml b/apm-sniffer/apm-agent-core/pom.xml index d251748fe3..43670f03ba 100644 --- a/apm-sniffer/apm-agent-core/pom.xml +++ b/apm-sniffer/apm-agent-core/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-agent-core diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 07cdd3e195..78a3b733ac 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-agent diff --git a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml index 19d0a0ac07..00abc003dc 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml index da27f49425..17f0dc4442 100644 --- a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml index 9dfc94d3f0..f2c5ac64f4 100644 --- a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml index fee4c87555..81ea378be9 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.84.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml index bd33a3f2de..d4897e1325 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-0.85.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml index 2e711d08f1..6a32acee05 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/apm-armeria-1.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-armeria-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml index d3bb98f95c..f55ffcb8fc 100644 --- a/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/apm-armeria-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml index 5b9862e235..fe491b9ee2 100644 --- a/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/asynchttpclient-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml index e58c105c66..cf5039fc31 100644 --- a/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/avro-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml index a9a5903d55..6716583e00 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml index 96e05ed0c8..7f31b50046 100644 --- a/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/baidu-brpc-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml index a6d5abaa51..7b7a82628a 100644 --- a/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/c3p0-0.9.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml index 143239cf4c..fd4b295a51 100644 --- a/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/canal-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml index f710b489eb..ecc5d3535d 100644 --- a/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cassandra-java-driver-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml index a669888e52..c80e82160b 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml index f02f4b7c73..e50763327d 100755 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml index 93f8952933..9744820eca 100644 --- a/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/cxf-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml index 7e073160b5..2ae4ae4b3f 100644 --- a/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dbcp-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml index 9b236f308f..bd8f9d6e39 100644 --- a/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/druid-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml index 0e9cee5454..4880f503ff 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml index 0c98cc6695..4608dc3006 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml index c092225837..f1eb7380c9 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml index 02d82c2341..48e35f1950 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml index 744e911633..70adb55678 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-conflict-patch/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml index a83f02078c..de7bd3752b 100644 --- a/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/dubbo-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml index 0d12e32ca6..01e5f81dfe 100644 --- a/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elastic-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml index 065469ee06..a965673abb 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticjob-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml index 224a41ee5e..6f048e9caf 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml index a727f273ee..e1a226cc08 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml index 1e22dbef16..89a90b55f2 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml index 1e43afaef4..51acbee581 100644 --- a/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml index 77b513f56b..a97bc44739 100644 --- a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml index 790a4b46a4..89f906c289 100644 --- a/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/finagle-6.25.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml index 9a0b7824df..170586098e 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-12.x-15.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml index 2fe40768a5..474b404f95 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-16plus-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml index 6de13ee103..cb6d9e0e02 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-8.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml index 4fef19e90f..d1e081d15c 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/graphql-9.x-plugin/pom.xml @@ -21,7 +21,7 @@ graphql-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml index ebbeb91191..74e296d1bd 100644 --- a/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/graphql-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml index 9b650f7cd9..191aa45db8 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml index 84699cac8b..5db8506875 100644 --- a/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grizzly-2.3.x-4.x-work-threadpool-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-grizzly-2.x-4.x-work-threadpool-plugin diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml index 12f7b140d8..72884e2d48 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-grpc-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml index 678218e2ba..d2ad8e9292 100644 --- a/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/guava-eventbus-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml index ad985a3ee7..4c359960a0 100755 --- a/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/h2-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml index 2809352c1b..d256acb1c5 100644 --- a/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hbase-1.x-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-hbase-1.x-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml index 330c7bcf37..864b91b125 100644 --- a/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hikaricp-3.x-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml index 00d5f64d55..0fcdd24c95 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-httpClient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml index 6b60405e18..2cd5025cd6 100644 --- a/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpasyncclient-4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-httpasyncclient-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml index 3203867e3a..2127da9e0d 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-3.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-httpclient-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml index f1a047e813..ba159639a4 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-httpclient-5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml index 37bedce74c..c9976aadf2 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/httpclient-commons/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-httpclient-commons diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml index 9ff2019872..b31ba12cf4 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/hutool-http-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ hutool-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml index 92249a85a5..6c41996fb0 100644 --- a/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hutool-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml index ba9914c170..83f8023afe 100644 --- a/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/hystrix-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml index f9e47326cf..e360c9ac4b 100644 --- a/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/influxdb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml index 46759160e6..1eecc0d35c 100755 --- a/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jdbc-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml index 9da30b3367..53f72f82af 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-2.x-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking jedis-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml index 3b72ba9d1b..4593b1c654 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ jedis-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml index 8b58716509..a337f0c2f8 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT diff --git a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml index 8d9f6824b1..f3a8001daf 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml index 0524344fdd..94fd991b19 100644 --- a/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jersey-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml index 79ffd36ac4..d800a09ddd 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml index 0d7545a5f2..be26052758 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.0-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml index 229c401f21..a7f7168743 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-client-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml index a5d993b031..c70f0ddd37 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml index 17049eadd7..d4602b83c4 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml @@ -20,7 +20,7 @@ jetty-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml index 230c49aff0..0d051bd4c0 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT jetty-plugins diff --git a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml index db583d1800..533868c65d 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml index b0d5740694..f4ef9b5118 100644 --- a/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jsonrpc4j-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml index 322b7fc81b..9870095054 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-commons/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-kafka-commons diff --git a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml index 1e3f0588a4..9c03ef164a 100644 --- a/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kafka-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml index 4bff437545..54d4d9e605 100644 --- a/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/kylin-jdbc-2.6.x-3.x-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml index facce0452d..c2158fcb4a 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking lettuce-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-lettuce-5.x-6.4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml index 1e4461f495..2bf20982cf 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking lettuce-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-lettuce-6.5.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml index 463250cf39..6062c90bce 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking lettuce-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-lettuce-common diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml index c9cfe8d17c..924a0e0ce7 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT lettuce-plugins diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml index 5785ce44cd..12b4e3a59e 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/light4j-plugin/pom.xml @@ -20,7 +20,7 @@ light4j-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml index 1d8da85b79..cd9ab3c418 100644 --- a/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/light4j-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT light4j-plugins diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml index 802ed1f44c..2ec8ab3063 100644 --- a/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mariadb-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml index dfd0f426bb..a0955c19d2 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml index 4d7e5f56de..a8fd47deac 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking micronaut-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml index 89fb218808..0025bcf432 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml index 1f2e130efb..e16638a4b9 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml index 6ff822a4a0..212222c6d6 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-mongodb-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml index de38fedcae..cb0363cb8e 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-mongodb-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml index d3319b9cdb..b74bc6d54d 100644 --- a/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/motan-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml index 441bf6601d..ff9f083f6d 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-commons/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml index 13d0cb16ff..ff678a1a00 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jdbc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml index 04687dbcc1..2f3dd90ea6 100644 --- a/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mssql-jtds-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml index ee171e5c32..361f5bc821 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-5.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml index 1e07e995b8..edaef2cf28 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml index b84115d907..11ee950a57 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml index c832784e25..92aa8ee5d8 100755 --- a/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/mysql-common/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml index 2d85d4cd9b..60bba313b0 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml index 0b98a3efe2..1bf1de4bfd 100644 --- a/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/neo4j-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml index 5c8a854b9b..2fc96f1c2f 100644 --- a/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/netty-socketio-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml index d1fe436ea6..3f2b4d0b67 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/http-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml index 2f968d2bf5..cd772375c6 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/mvc-annotation-1.x-plugin/pom.xml @@ -20,7 +20,7 @@ nutz-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml index 711786d120..0b8fe2d545 100644 --- a/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nutz-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT nutz-plugins diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml index ede53c4ff8..14d05d0135 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml index ef6fcb0239..b25f764a6e 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml index a8d0a42612..ce5434d9cb 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml index 96d60b3765..68437b314a 100644 --- a/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/okhttp-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml index 26491de16c..5c74e133d8 100644 --- a/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/play-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-play-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index ea21985349..1c792ed425 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking java-agent-sniffer - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-sdk-plugin diff --git a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml index 4ce5b69ecd..181a48d08c 100755 --- a/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/postgresql-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml index 98a45766bb..862269d01e 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.2-2.7-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml index fbe2c3fe00..c464911398 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-2.8.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml index 7fa0685161..9679ea88fb 100644 --- a/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pulsar-common/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml index 99bd15fb4f..a980a658d8 100644 --- a/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/quasar-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-quasar-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml index 65f78a5467..492b479b07 100644 --- a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml index 55edbdeac3..7ba9d05be3 100644 --- a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-redisson-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml index 6ff7caaaaa..4f661c38ba 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT resteasy-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml index 14d989003f..83b9d357cc 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT resteasy-server-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml index f21d450b6a..63eb0c4826 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT resteasy-server-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml index f259291bfd..f20ab70b3e 100644 --- a/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/resteasy-plugin/resteasy-server-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ resteasy-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT resteasy-server-6.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml index 6b206013d9..5a7c711dd2 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml index 6fa277b4ef..a30e1b09e0 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml index ad51da8c77..62c1fbb3e3 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml index d07527b994..e4dc8d8988 100644 --- a/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/rocketMQ-client-java-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml index e010d7cc09..06f9d58672 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml index f92f636768..6c26908ce4 100644 --- a/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servicecomb-plugin/servicecomb-java-chassis-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ servicecomb-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml index 60d101c987..6d38f040f2 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml index 48776bf7e7..033f5afc04 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml index cdbdf13335..fa282b6571 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.0.x-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml index 99b838e1e7..803c61dbeb 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-4.1.0-plugin/pom.xml @@ -20,7 +20,7 @@ shardingsphere-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml index 013e5929ed..e17d47b46d 100644 --- a/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/shardingsphere-plugins/sharding-sphere-5.0.0-plugin/pom.xml @@ -21,7 +21,7 @@ shardingsphere-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml index c685c69dd7..21f8795238 100644 --- a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/src/test/java/org/apache/skywalking/apm/plugin/sofarpc/InvokeCallbackWrapperTest.java b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/src/test/java/org/apache/skywalking/apm/plugin/sofarpc/InvokeCallbackWrapperTest.java index ef9c9f3cb0..d05d4026c2 100644 --- a/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/src/test/java/org/apache/skywalking/apm/plugin/sofarpc/InvokeCallbackWrapperTest.java +++ b/apm-sniffer/apm-sdk-plugin/sofarpc-plugin/src/test/java/org/apache/skywalking/apm/plugin/sofarpc/InvokeCallbackWrapperTest.java @@ -141,7 +141,10 @@ public void testOnResponse() throws InterruptedException { TraceSegment traceSegment2 = segmentStorage.getTraceSegments().get(1); List spans2 = SegmentHelper.getSpans(traceSegment2); assertThat(spans2.size(), is(1)); - assertEquals("sofarpc", traceSegment2.getRef().getParentEndpoint()); + + // Segment order is non-deterministic; find the child segment (the one with a ref) + TraceSegment childSegment = traceSegment.getRef() != null ? traceSegment : traceSegment2; + assertEquals("sofarpc", childSegment.getRef().getParentEndpoint()); } @Test @@ -162,7 +165,11 @@ public void testOnException() throws InterruptedException { TraceSegment traceSegment2 = segmentStorage.getTraceSegments().get(1); List spans2 = SegmentHelper.getSpans(traceSegment2); assertThat(spans2.size(), is(1)); - assertThat(SpanHelper.getLogs(spans2.get(0)).size(), is(1)); + + // Segment order is non-deterministic; find the child segment (the one with a ref) + TraceSegment childSegment = traceSegment.getRef() != null ? traceSegment : traceSegment2; + List childSpans = SegmentHelper.getSpans(childSegment); + assertThat(SpanHelper.getLogs(childSpans.get(0)).size(), is(1)); } diff --git a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml index 5221d63d04..543d27c2c4 100644 --- a/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/solon-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT solon-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml index f8b02211f4..2377a233f7 100644 --- a/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/solrj-7.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml index 556c7f269a..337a154135 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml index 8c922b6c28..fa85530d61 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/concurrent-util-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml index 0b367dffe7..58e530913a 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/core-patch/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml index a3ad988877..02fa8639d0 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml index d551f811a0..f48ace4499 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml index c8eae36531..bea4ce00a9 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/pom.xml @@ -19,7 +19,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml index 67bcaaac46..65c554bb88 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml index 10b0268892..609220e725 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT spring-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml index 2b8cb9beed..2dab6a46c9 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml index 9bcaa96cbf..966de1995f 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml index 7317ad938a..19ecc7989c 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/resttemplate-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml index 3bb2740074..c4dfd6d15f 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/scheduled-annotation-plugin/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml index 7df17507ae..34769eadbb 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT netflix-plugins diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml index 4a76383083..6fb11aaa57 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/netflix-plugins/spring-cloud-feign-1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking netflix-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-spring-cloud-feign-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml index 19d050291c..d1f4409bce 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT spring-cloud diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml index bd7a6d2f3f..579c404b7a 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-cloud/spring-cloud-feign-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking spring-cloud - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-spring-cloud-feign-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml index 7e1ff15179..ff67ee32df 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-commons/pom.xml @@ -20,7 +20,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml index a8afa0c54a..d8bf75bf9e 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-1.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-spring-kafka-1.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml index 267f56a506..2cff5cf300 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-kafka-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking spring-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-spring-kafka-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml index 2c818ab342..1a3cfbfeb7 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml index 6d50169112..6f67c4b024 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-6.x-webclient-plugin/pom.xml @@ -21,7 +21,7 @@ spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml index 4eda0fae4c..1b123e2207 100644 --- a/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spymemcached-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-spymemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml index 9e164a9477..eb3e342fd3 100644 --- a/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/struts2-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml index c481a809ef..dc51e01a99 100644 --- a/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/thrift-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml index ca896b0cef..62896f4b61 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml index 7307cd3f9a..0763bcca65 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml @@ -20,7 +20,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml index 7c5eb5597b..2007b9711e 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml index 10a4132bfd..14d23e7692 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT undertow-plugins diff --git a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml index 952be80876..8b722364c6 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-plugins/undertow-2.x-plugin/pom.xml @@ -20,7 +20,7 @@ undertow-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml index a46b602982..aed38b73f1 100644 --- a/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/undertow-worker-thread-pool-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml index a33ebb009e..a7f441800d 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT vertx-plugins diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml index 1a33046229..b1d89698a5 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-3.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml index 981b6bdd3d..9e21fe716a 100644 --- a/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/vertx-plugins/vertx-core-4.x-plugin/pom.xml @@ -20,7 +20,7 @@ vertx-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml index 4d1971ea07..7795fd9659 100644 --- a/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/websphere-liberty-23.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml index fa896a48e2..35876e8aff 100644 --- a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking apm-sdk-plugin - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-xmemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml index 5566ea223c..da1409f18d 100644 --- a/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/xxl-job-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ apm-sdk-plugin org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-test-tools/pom.xml b/apm-sniffer/apm-test-tools/pom.xml index 8b406e428e..9dd0f43cb3 100644 --- a/apm-sniffer/apm-test-tools/pom.xml +++ b/apm-sniffer/apm-test-tools/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent-sniffer - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-test-tools diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml index c14b96205e..a914b8d528 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-kafka-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml index b3a5651b21..86e57d28bb 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml index 747d520d74..5e1a0fb598 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-log4j-2.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml index 75b3b31866..341faac073 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logback-1.x-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml index 57033d5b09..ae19d88816 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-logging-common/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml index c04acb613b..4d260f63e5 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml index fb6e91be34..7e9c7d103f 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-micrometer-activation/pom.xml @@ -20,7 +20,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml index a260c73ed8..05dc1b4ac9 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml index e0d378caea..f93d0a3397 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml index b82def92b1..d8832e24f5 100644 --- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-webflux-activation/pom.xml @@ -21,7 +21,7 @@ apm-toolkit-activation org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/apm-toolkit-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/pom.xml index 09206213e1..f6e3b542c5 100644 --- a/apm-sniffer/apm-toolkit-activation/pom.xml +++ b/apm-sniffer/apm-toolkit-activation/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml index 94de5b8c2a..5de97c5a33 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-forkjoinpool-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml index 8bfa622165..1692e684a6 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-http-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 @@ -33,7 +33,7 @@ UTF-8 - + diff --git a/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/pom.xml index 88a0f72a99..f537f685e6 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-httpclient-plugin/pom.xml @@ -20,7 +20,7 @@ bootstrap-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml index 6bed3de12b..33dd7a3b4d 100755 --- a/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threading-plugin/pom.xml @@ -20,7 +20,7 @@ org.apache.skywalking bootstrap-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml index ca7eb8cac7..3da184c381 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-threadpool-plugin/pom.xml @@ -20,7 +20,7 @@ bootstrap-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml index 67766ef3eb..9a3eee820f 100644 --- a/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml +++ b/apm-sniffer/bootstrap-plugins/jdk-virtual-thread-executor-plugin/pom.xml @@ -20,7 +20,7 @@ bootstrap-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bootstrap-plugins/pom.xml b/apm-sniffer/bootstrap-plugins/pom.xml index cf1285cc07..fe3bf24930 100644 --- a/apm-sniffer/bootstrap-plugins/pom.xml +++ b/apm-sniffer/bootstrap-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/bytebuddy-patch/pom.xml b/apm-sniffer/bytebuddy-patch/pom.xml index 60b20cffe9..460631dfc3 100644 --- a/apm-sniffer/bytebuddy-patch/pom.xml +++ b/apm-sniffer/bytebuddy-patch/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking java-agent-sniffer - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml index 5ac2465450..5dfd4ed7ab 100644 --- a/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml +++ b/apm-sniffer/expired-plugins/impala-jdbc-2.6.x-plugin/pom.xml @@ -24,7 +24,7 @@ org.apache.skywalking expired-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-impala-jdbc-2.6.x-plugin diff --git a/apm-sniffer/expired-plugins/pom.xml b/apm-sniffer/expired-plugins/pom.xml index f33497cec5..4385464c61 100644 --- a/apm-sniffer/expired-plugins/pom.xml +++ b/apm-sniffer/expired-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml index 8428e0e60e..89d8d96b65 100644 --- a/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/caffeine-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-caffeine-3.x-plugin diff --git a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml index 14fc75ee0e..fb100e0d94 100644 --- a/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/customize-enhance-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml index 9dea5174c9..60906ea1df 100644 --- a/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/ehcache-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml index 630524d970..fd47548245 100644 --- a/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/fastjson-1.2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-fastjson-1.x-plugin diff --git a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml index f45e92d2f5..3cacbd71f0 100644 --- a/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/gson-2.8.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-gson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml index e32c47ce81..4b678e32ed 100644 --- a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-guava-cache-plugin diff --git a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml index 1b1d26a818..6cc5017d9c 100644 --- a/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/jackson-2.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-jackson-2.x-plugin diff --git a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml index 0f55f43e47..ab831b6c1b 100644 --- a/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/kotlin-coroutine-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-kotlin-coroutine-plugin diff --git a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml index 84ba662bcf..7da71f0c1c 100644 --- a/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/mybatis-3.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-mybatis-3.x-plugin diff --git a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml index acbd852ce7..7f5ea9441e 100644 --- a/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/nacos-client-2.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml index daeacb30d2..b8313a57c7 100644 --- a/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/netty-http-4.1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml index b7f5b84a75..a2399d0bc6 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/mvc-annotation-6.x-plugin/pom.xml @@ -19,7 +19,7 @@ optional-spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml index b798e59499..b2963c4c23 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.0.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-spring-cloud-gateway-2.0.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml index e5b6e7e100..c9a0dfb040 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-cloud - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-spring-cloud-gateway-2.1.x-plugin diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml index 5bfe88aef2..33180c560c 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml index d890c84e7c..bcd6ffcca4 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-cloud org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml index 281fb79f0e..8e5547689c 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-spring-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT optional-spring-cloud diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml index 344126cd75..3b34789ab4 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 pom diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml index 18d0a3037c..8fc5797da0 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/resttemplate-6.x-plugin/pom.xml @@ -20,7 +20,7 @@ optional-spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml index e943d2451c..367a58c61b 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml index f03fd451c0..74f0694de2 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 jar diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml index 2ef8246634..e597375432 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml index ca9e22a8d0..98c5f9bc71 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-6.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-spring-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml index 143a79f94b..c1d0d8adb7 100644 --- a/apm-sniffer/optional-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml index ab9894e133..acc3b85a35 100644 --- a/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/quartz-scheduler-2.x-plugin/pom.xml @@ -23,7 +23,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-quartz-scheduler-2.x-plugin diff --git a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml index c3c4a2f162..fd4abb4af5 100644 --- a/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/sentinel-1.x-plugin/pom.xml @@ -21,7 +21,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml index 10f4d208fa..7f712e7582 100644 --- a/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/shenyu-2.4.x-plugin/pom.xml @@ -21,7 +21,7 @@ optional-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml index 32d5002b57..ec9d193fc6 100644 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml index b2dfdfdfe9..cc4f683ed6 100644 --- a/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-sampler-cpu-policy-plugin/pom.xml @@ -20,7 +20,7 @@ optional-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml index 723e675445..530f490fd5 100644 --- a/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/zookeeper-3.4.x-plugin/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking optional-plugins - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT apm-zookeeper-3.4.x-plugin diff --git a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml index 15026e49df..52374f2631 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-config-extension/pom.xml @@ -20,7 +20,7 @@ optional-reporter-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml index 99b9cf3679..127e923448 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/pom.xml @@ -21,7 +21,7 @@ optional-reporter-plugins org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/optional-reporter-plugins/pom.xml b/apm-sniffer/optional-reporter-plugins/pom.xml index 260ddc308b..13b9fc86f7 100644 --- a/apm-sniffer/optional-reporter-plugins/pom.xml +++ b/apm-sniffer/optional-reporter-plugins/pom.xml @@ -21,7 +21,7 @@ java-agent-sniffer org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/apm-sniffer/pom.xml b/apm-sniffer/pom.xml index 4cb926b474..94ea5a16bd 100644 --- a/apm-sniffer/pom.xml +++ b/apm-sniffer/pom.xml @@ -21,7 +21,7 @@ java-agent org.apache.skywalking - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT 4.0.0 diff --git a/changes/changes-9.6.0.md b/changes/changes-9.6.0.md new file mode 100644 index 0000000000..74a4739aaa --- /dev/null +++ b/changes/changes-9.6.0.md @@ -0,0 +1,33 @@ +Changes by Version +================== +Release Notes. + +9.6.0 +------------------ + +* Add CLAUDE.md for AI assistant guidance. +* Bump up agent-oap protocol to latest(16c51358ebcf42629bf4ffdf952253971f20eb25). +* Bump up gRPC to v1.74.0. +* Bump up netty to v4.1.124.Final. +* Bump up GSON to v2.13.1. +* Bump up guava to v32.1.3. +* Bump up oap to the 10.3-dev.latest(dc8740d4757b35374283c4850a9a080e40f0eb79) in e2e. +* Bump up cli to the 0.15.0-dev.latest(77b4c49e89c9c000278f44e62729d534f2ec842e) in e2e. +* Bump up apache parent pom to v35. +* Update Maven to 3.6.3 in mvnw. +* Fix OOM due to too many span logs. +* Fix ClassLoader cache OOM issue with WeakHashMap. +* Fix Jetty client cannot receive the HTTP response body. +* Eliminate repeated code with HttpServletRequestWrapper in mvc-annotation-commons. +* Add the jdk httpclient plugin. +* Fix Gateway 2.0.x plugin not activated for spring-cloud-starter-gateway 2.0.0.RELEASE. +* Support kafka-clients-3.9.x intercept. +* Upgrade kafka-clients version in optional-reporter-plugins to 3.9.1. +* Fix AbstractLogger replaceParam when the replaced string contains a replacement marker. +* Fix `JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH` was not working in some plugins. +* Bump up Lombok to v1.18.42 to adopt JDK25 compiling. +* Add `eclipse-temurin:25-jre` as another base image. +* Add JDK25 plugin tests for Spring 6. +* Ignore classes starting with "sun.nio.cs" in bytebuddy due to potential class loading deadlock. + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) diff --git a/pom.xml b/pom.xml index 8e85a9cee4..8260a17784 100755 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ org.apache.skywalking java-agent - 9.6.0-SNAPSHOT + 9.7.0-SNAPSHOT org.apache diff --git a/test/plugin/containers/jvm-container/src/main/docker/run.sh b/test/plugin/containers/jvm-container/src/main/docker/run.sh index 9d1327c621..3a70fe4930 100644 --- a/test/plugin/containers/jvm-container/src/main/docker/run.sh +++ b/test/plugin/containers/jvm-container/src/main/docker/run.sh @@ -24,7 +24,10 @@ exitOnError() { } exitAndClean() { - [[ -n $DEBUG_MODE ]] && exit $1; + if [[ -n $DEBUG_MODE ]]; then + chmod -R a+r ${SCENARIO_HOME} 2>/dev/null + exit $1 + fi [[ -f ${SCENARIO_HOME}/data/actualData.yaml ]] && rm -rf ${SCENARIO_HOME}/data/actualData.yaml [[ -d ${LOGS_HOME} ]] && rm -rf ${LOGS_HOME} @@ -84,7 +87,7 @@ export agent_opts=" -Dskywalking.meter.report_interval=1 -Xms256m -Xmx256m ${agent_opts}" -bash /var/run/${SCENARIO_NAME}/${SCENARIO_START_SCRIPT} 1>${LOGS_HOME}/scenario.out & +bash /var/run/${SCENARIO_NAME}/${SCENARIO_START_SCRIPT} >${LOGS_HOME}/scenario.out 2>&1 & sleep 5 healthCheck ${SCENARIO_HEALTH_CHECK_URL} diff --git a/test/plugin/runner-helper/src/main/resources/compose-start-script.template b/test/plugin/runner-helper/src/main/resources/compose-start-script.template index 3ef6a15466..c94e415bf2 100644 --- a/test/plugin/runner-helper/src/main/resources/compose-start-script.template +++ b/test/plugin/runner-helper/src/main/resources/compose-start-script.template @@ -26,16 +26,47 @@ docker_container_name="${docker_container_name}_1" <#noparse> container_name="${project_name}_${docker_container_name}" -docker compose -p ${project_name} -f ${compose_file} up -d + +# Diagnostic: log docker compose version +docker compose version >&2 || true + +echo "=== Starting docker compose ===" >&2 +compose_output=$(docker compose -p ${project_name} -f ${compose_file} up -d 2>&1) +compose_exit=$? +echo "${compose_output}" >&2 +if [[ ${compose_exit} -ne 0 ]]; then + echo "docker compose up exited with code ${compose_exit}" >&2 +fi container_id=`docker ps -qf "name=${container_name}"` if [[ -z "${container_id}" ]]; then - echo "docker startup failure!" >&2 + echo "docker startup failure! container_name=${container_name} not found." >&2 + echo "=== docker ps -a ===" >&2 + docker ps -a >&2 || true + echo "=== docker compose logs ===" >&2 + docker compose -p ${project_name} -f ${compose_file} logs 2>&1 >&2 || true + # Create container.log with diagnostic info + mkdir -p ${SCENARIO_HOME}/logs + { + echo "=== CONTAINER STARTUP FAILURE ===" + echo "container_name=${container_name} was not found by docker ps" + echo "compose_exit_code=${compose_exit}" + echo "compose_output:" + echo "${compose_output}" + echo "=== docker ps -a ===" + docker ps -a 2>&1 || true + echo "=== docker compose logs ===" + docker compose -p ${project_name} -f ${compose_file} logs 2>&1 || true + } >${SCENARIO_HOME}/logs/container.log + docker compose -p ${project_name} -f ${compose_file} kill 2>/dev/null || true + docker compose -p ${project_name} -f ${compose_file} rm -f 2>/dev/null || true status=1 else status=`docker wait ${container_id}` [[ $status -ne 0 ]] && docker logs ${container_id} >&2 + # Recreate logs dir in case the container removed it via volume mount + mkdir -p ${SCENARIO_HOME}/logs docker logs ${container_id} >${SCENARIO_HOME}/logs/container.log docker compose -p ${project_name} -f ${compose_file} kill diff --git a/test/plugin/runner-helper/src/main/resources/container-start-script.template b/test/plugin/runner-helper/src/main/resources/container-start-script.template index 0f072afdf1..97ee284649 100644 --- a/test/plugin/runner-helper/src/main/resources/container-start-script.template +++ b/test/plugin/runner-helper/src/main/resources/container-start-script.template @@ -47,13 +47,25 @@ sleep 3 container_name=`docker ps -aqf "name=${docker_container_name}"` <#noparse> -status=$(docker wait ${container_name}) - if [[ -z ${container_name} ]]; then echo "docker startup failure!" >&2 + echo "=== docker ps -a ===" >&2 + docker ps -a >&2 || true + # Create container.log with diagnostic info + mkdir -p ${SCENARIO_HOME}/logs + { + echo "=== CONTAINER STARTUP FAILURE ===" + echo "Container not found by docker ps" + echo "=== docker ps -a ===" + docker ps -a 2>&1 || true + } >${SCENARIO_HOME}/logs/container.log status=1 else + status=$(docker wait ${container_name}) + [[ $status -ne 0 ]] && docker logs ${container_name} >&2 + # Recreate logs dir in case the container removed it via volume mount + mkdir -p ${SCENARIO_HOME}/logs docker logs ${container_name} >${SCENARIO_HOME}/logs/container.log docker container rm -f $container_name fi diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/configuration.yml b/test/plugin/scenarios/elasticsearch-7.x-scenario/configuration.yml index 853e67498e..aa43501041 100644 --- a/test/plugin/scenarios/elasticsearch-7.x-scenario/configuration.yml +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/configuration.yml @@ -22,7 +22,7 @@ environment: - elasticsearch.server=elasticsearch-server-7.x:9200 dependencies: elasticsearch-server-7.x: - image: elasticsearch:${CASE_SERVER_IMAGE_VERSION} + image: docker.elastic.co/elasticsearch/elasticsearch:${CASE_SERVER_IMAGE_VERSION} hostname: elasticsearch-server-7.x removeOnExit: true expose: @@ -30,6 +30,5 @@ dependencies: environment: - cluster.name=docker-node - xpack.security.enabled=false - - bootstrap.memory_lock=true - - "ES_JAVA_OPTS=-Xms256m -Xmx256m" + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - discovery.type=single-node diff --git a/test/plugin/scenarios/elasticsearch-7.x-scenario/support-version.list b/test/plugin/scenarios/elasticsearch-7.x-scenario/support-version.list index d5108d7a3c..e5b98548c6 100644 --- a/test/plugin/scenarios/elasticsearch-7.x-scenario/support-version.list +++ b/test/plugin/scenarios/elasticsearch-7.x-scenario/support-version.list @@ -27,5 +27,4 @@ 7.12.1 7.13.4 7.14.2 -7.16.3 7.17.21 \ No newline at end of file diff --git a/test/plugin/scenarios/elasticsearch-rest-high-level-6.x-scenario/configuration.yml b/test/plugin/scenarios/elasticsearch-rest-high-level-6.x-scenario/configuration.yml index bab1c5a875..72c856d395 100644 --- a/test/plugin/scenarios/elasticsearch-rest-high-level-6.x-scenario/configuration.yml +++ b/test/plugin/scenarios/elasticsearch-rest-high-level-6.x-scenario/configuration.yml @@ -20,7 +20,7 @@ environment: - elasticsearch.server=elasticsearch-server-6.x:9200 dependencies: elasticsearch-server-6.x: - image: elasticsearch:${CASE_SERVER_IMAGE_VERSION} + image: docker.elastic.co/elasticsearch/elasticsearch:${CASE_SERVER_IMAGE_VERSION} hostname: elasticsearch-server-6.x removeOnExit: true expose: diff --git a/test/plugin/scenarios/rocketmq-5-grpc-scenario/pom.xml b/test/plugin/scenarios/rocketmq-5-grpc-scenario/pom.xml index d27b6488b1..018ce5430e 100644 --- a/test/plugin/scenarios/rocketmq-5-grpc-scenario/pom.xml +++ b/test/plugin/scenarios/rocketmq-5-grpc-scenario/pom.xml @@ -34,7 +34,7 @@ 1.8 3.8.1 5.0.5 - 5.1.1 + 5.1.4 2.1.6.RELEASE 1.18.20 diff --git a/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/CaseController.java b/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/CaseController.java index 5219bc8db9..313389913e 100644 --- a/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/CaseController.java +++ b/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/CaseController.java @@ -48,35 +48,27 @@ public class CaseController { @Autowired private MessageService messageService; + private volatile boolean consumerStarted = false; + @RequestMapping("/rocketmq-5-grpc-scenario") @ResponseBody public String testcase() { try { messageService.sendNormalMessage(NORMAL_TOPIC, TAG_NOMARL, GROUP); - Thread t1 = new Thread(() -> messageService.pushConsumes( - Collections.singletonList(NORMAL_TOPIC), - Collections.singletonList(TAG_NOMARL), - GROUP - )); - t1.start(); - t1.join(); messageService.sendNormalMessageAsync(ASYNC_PRODUCER_TOPIC, TAG_ASYNC_PRODUCER, GROUP); messageService.sendNormalMessageAsync(ASYNC_PRODUCER_TOPIC, TAG_ASYNC_PRODUCER, GROUP); - Thread t2 = new Thread(() -> messageService.simpleConsumes(Collections.singletonList(ASYNC_PRODUCER_TOPIC), - Collections.singletonList(TAG_ASYNC_PRODUCER), GROUP, - 10, 10 - )); - t2.start(); - t2.join(); + new Thread(() -> messageService.simpleConsumes( + Collections.singletonList(ASYNC_PRODUCER_TOPIC), + Collections.singletonList(TAG_ASYNC_PRODUCER), GROUP, + 10, 10 + )).start(); messageService.sendNormalMessage(ASYNC_CONSUMER_TOPIC, TAG_ASYNC_CONSUMER, GROUP); messageService.sendNormalMessage(ASYNC_CONSUMER_TOPIC, TAG_ASYNC_CONSUMER, GROUP); - Thread t3 = new Thread(() -> messageService.simpleConsumeAsync(ASYNC_CONSUMER_TOPIC, TAG_ASYNC_CONSUMER, GROUP, 10, - 10 - )); - t3.start(); - t3.join(); + new Thread(() -> messageService.simpleConsumeAsync( + ASYNC_CONSUMER_TOPIC, TAG_ASYNC_CONSUMER, GROUP, 10, 10 + )).start(); } catch (Exception e) { log.error("testcase error", e); } @@ -86,11 +78,45 @@ public String testcase() { @RequestMapping("/healthCheck") @ResponseBody public String healthCheck() throws Exception { - System.setProperty(MixAll.ROCKETMQ_HOME_ENV, this.getClass().getResource("/").getPath()); - messageService.updateNormalTopic(NORMAL_TOPIC); - messageService.updateNormalTopic(ASYNC_PRODUCER_TOPIC); - messageService.updateNormalTopic(ASYNC_CONSUMER_TOPIC); - final Producer producer = ProducerSingleton.getInstance(endpoints, NORMAL_TOPIC); + if (!consumerStarted) { + // Set flag early to prevent re-entry from concurrent healthCheck + // requests (each curl has a 3s timeout, and initialization may + // take longer than that). + consumerStarted = true; + try { + System.setProperty(MixAll.ROCKETMQ_HOME_ENV, this.getClass().getResource("/").getPath()); + messageService.updateNormalTopic(NORMAL_TOPIC); + messageService.updateNormalTopic(ASYNC_PRODUCER_TOPIC); + messageService.updateNormalTopic(ASYNC_CONSUMER_TOPIC); + // Start push consumer early so it has time to receive messages + messageService.pushConsumes( + Collections.singletonList(NORMAL_TOPIC), + Collections.singletonList(TAG_NOMARL), + GROUP + ); + final Producer producer = ProducerSingleton.getInstance(endpoints, NORMAL_TOPIC); + // Send a probe message so the consumer has something to receive + messageService.sendNormalMessage(NORMAL_TOPIC, TAG_NOMARL, GROUP); + } catch (Exception e) { + consumerStarted = false; + throw e; + } + } + + // Wait until the consumer has actually received a probe message, + // confirming it can consume from the topic. + // Send a fresh probe on every retry so the consumer picks it up once + // rebalance finishes (messages sent before rebalance may never arrive). + if (!MessageService.CONSUMER_READY) { + try { + messageService.sendNormalMessage(NORMAL_TOPIC, TAG_NOMARL, GROUP); + System.out.printf("HealthCheck: sent probe message (consumer not ready yet).%n"); + } catch (Exception e) { + System.out.printf("HealthCheck: failed to send probe: %s%n", e.getMessage()); + } + throw new RuntimeException("Consumer has not received probe message yet"); + } + return SUCCESS; } } diff --git a/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/MessageService.java b/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/MessageService.java index f7d4dc3c9b..33b9bad539 100644 --- a/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/MessageService.java +++ b/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/client/java/controller/MessageService.java @@ -203,26 +203,23 @@ public void simpleConsumeAsync(String topic, maxMessageNum, invisibleDuration ); - future0.whenCompleteAsync((messages, throwable) -> { - if (null != throwable) { - log.error("Failed to receive message from remote", throwable); - return; - } + future0.thenComposeAsync(messages -> { log.info("Received {} message(s)", messages.size()); final Map> map = messages.stream().collect(Collectors.toMap(message -> message, consumer::ackAsync)); - for (Map.Entry> entry : map.entrySet()) { + List> ackFutures = map.entrySet().stream().map(entry -> { final MessageId messageId = entry.getKey().getMessageId(); final CompletableFuture future = entry.getValue(); - future.whenCompleteAsync((v, t) -> { + return future.whenCompleteAsync((v, t) -> { if (null != t) { log.error("Message is failed to be acknowledged, messageId={}", messageId, t); return; } log.info("Message is acknowledged successfully, messageId={}", messageId); }, ackCallbackExecutor); - } - }, receiveCallbackExecutor); + }).collect(Collectors.toList()); + return CompletableFuture.allOf(ackFutures.toArray(new CompletableFuture[0])); + }, receiveCallbackExecutor).join(); } catch (Exception e) { log.error("consumer start error", e); } @@ -243,6 +240,8 @@ public void updateNormalTopic(String topic) { MQAdminStartup.main(subArgs); } + public static volatile boolean CONSUMER_READY = false; + public static class MyConsumer implements MessageListener { @Override @@ -250,6 +249,7 @@ public ConsumeResult consume(MessageView messageView) { log.info("Consume message successfully, messageId={},messageBody={}", messageView.getMessageId(), messageView.getBody().toString() ); + CONSUMER_READY = true; return ConsumeResult.SUCCESS; } } diff --git a/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/resources/log4j2.xml index 9849ed5a8a..b16354bfa3 100644 --- a/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/resources/log4j2.xml +++ b/test/plugin/scenarios/rocketmq-5-grpc-scenario/src/main/resources/log4j2.xml @@ -23,7 +23,7 @@ - + diff --git a/test/plugin/scenarios/rocketmq-5-grpc-scenario/support-version.list b/test/plugin/scenarios/rocketmq-5-grpc-scenario/support-version.list index 4f8dd365dc..da0221c8c1 100644 --- a/test/plugin/scenarios/rocketmq-5-grpc-scenario/support-version.list +++ b/test/plugin/scenarios/rocketmq-5-grpc-scenario/support-version.list @@ -16,5 +16,4 @@ # lists your version here (Contains only the last version number of each minor version.) -5.1.1 5.1.4 diff --git a/test/plugin/scenarios/rocketmq-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/controller/CaseController.java b/test/plugin/scenarios/rocketmq-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/controller/CaseController.java index ab96fd6a7c..85d32069a5 100644 --- a/test/plugin/scenarios/rocketmq-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/controller/CaseController.java +++ b/test/plugin/scenarios/rocketmq-scenario/src/main/java/test/apache/skywalking/apm/testcase/rocketmq/controller/CaseController.java @@ -25,6 +25,7 @@ import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; import org.apache.rocketmq.common.message.Message; import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.remoting.common.RemotingHelper; @@ -47,17 +48,19 @@ public class CaseController { @Value("${name.server}") private String namerServer; + private volatile boolean consumerStarted = false; + private volatile boolean consumerReady = false; + private DefaultMQProducer probeProducer; + @RequestMapping("/rocketmq-scenario") @ResponseBody public String testcase() { try { - // start producer DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name"); producer.setNamesrvAddr(namerServer); producer.start(); System.out.printf("Provider Started.%n"); - // send msg Message msg = new Message("TopicTest", ("Hello RocketMQ sendMsg " + new Date()).getBytes(RemotingHelper.DEFAULT_CHARSET) ); @@ -65,30 +68,6 @@ public String testcase() { msg.setKeys("KeyA"); SendResult sendResult = producer.send(msg); System.out.printf("%s send msg: %s%n", new Date(), sendResult); - - // start consumer - Thread thread = new Thread(new Runnable() { - @Override - public void run() { - try { - DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name"); - consumer.setNamesrvAddr(namerServer); - consumer.subscribe("TopicTest", "*"); - consumer.registerMessageListener(new MessageListenerConcurrently() { - @Override - public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { - System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msgs.get(0).getBody(), StandardCharsets.UTF_8)); - return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; - } - }); - consumer.start(); - System.out.printf("Consumer Started.%n"); - } catch (Exception e) { - log.error("consumer start error", e); - } - } - }); - thread.start(); } catch (Exception e) { log.error("testcase error", e); } @@ -98,11 +77,60 @@ public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeCo @RequestMapping("/healthCheck") @ResponseBody public String healthCheck() throws Exception { - // start producer - DefaultMQProducer producer = new DefaultMQProducer("healthCheck_please_rename_unique_group_name"); - producer.setNamesrvAddr(namerServer); - producer.start(); - System.out.printf("HealthCheck Provider Started.%n"); + if (!consumerStarted) { + // Set flag early to prevent re-entry from concurrent healthCheck + // requests (each curl has a 3s timeout, and initialization may + // take longer than that). + consumerStarted = true; + try { + // Speed up client-side rebalance from default 20s to 2s so the + // consumer discovers topic queues faster after startup. + System.setProperty("rocketmq.client.rebalance.waitInterval", "2000"); + + // Start a producer that stays alive to send probe messages on each retry. + probeProducer = new DefaultMQProducer("healthCheck_please_rename_unique_group_name"); + probeProducer.setNamesrvAddr(namerServer); + probeProducer.start(); + Message probeMsg = new Message("TopicTest", "probe".getBytes(StandardCharsets.UTF_8)); + probeProducer.send(probeMsg); + System.out.printf("HealthCheck: Topic created via probe message.%n"); + + // Start consumer after topic exists so rebalance finds queues immediately. + DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name"); + consumer.setNamesrvAddr(namerServer); + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET); + consumer.subscribe("TopicTest", "*"); + consumer.registerMessageListener(new MessageListenerConcurrently() { + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), new String(msgs.get(0).getBody(), StandardCharsets.UTF_8)); + consumerReady = true; + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + }); + consumer.start(); + System.out.printf("Consumer Started.%n"); + } catch (Exception e) { + consumerStarted = false; + throw e; + } + } + + // Wait until the consumer has actually received a probe message, + // confirming rebalance is complete and it can consume from the topic. + // Send a fresh probe on every retry so the consumer picks it up once + // rebalance finishes (messages sent before rebalance may never arrive). + if (!consumerReady) { + try { + Message probeMsg = new Message("TopicTest", "probe".getBytes(StandardCharsets.UTF_8)); + probeProducer.send(probeMsg); + System.out.printf("HealthCheck: sent probe message (consumer not ready yet).%n"); + } catch (Exception e) { + System.out.printf("HealthCheck: failed to send probe: %s%n", e.getMessage()); + } + throw new RuntimeException("Consumer has not received probe message yet"); + } + return SUCCESS; } diff --git a/test/plugin/scenarios/rocketmq-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/rocketmq-scenario/src/main/resources/log4j2.xml index 9849ed5a8a..b16354bfa3 100644 --- a/test/plugin/scenarios/rocketmq-scenario/src/main/resources/log4j2.xml +++ b/test/plugin/scenarios/rocketmq-scenario/src/main/resources/log4j2.xml @@ -23,7 +23,7 @@ - + diff --git a/test/plugin/scenarios/rocketmq-scenario/support-version.list b/test/plugin/scenarios/rocketmq-scenario/support-version.list index b391ea9d2a..7de5cb6f6d 100644 --- a/test/plugin/scenarios/rocketmq-scenario/support-version.list +++ b/test/plugin/scenarios/rocketmq-scenario/support-version.list @@ -16,7 +16,7 @@ # lists your version here (Contains only the last version number of each minor version.) -5.1.0 +5.1.4 4.9.4 4.8.0 4.7.1 From ad5f8eee17748d2961080e4a0cae2178207f9bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Sun, 22 Feb 2026 12:24:35 +0800 Subject: [PATCH 091/114] Fix docker.push25 typo in release guide (#792) The make target `docker.push25` should be `docker.push.java25` to match the Makefile pattern `docker.push.%` with base.all entries. --- docs/en/contribution/release-java-agent.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/contribution/release-java-agent.md b/docs/en/contribution/release-java-agent.md index f0149636da..567cf81615 100644 --- a/docs/en/contribution/release-java-agent.md +++ b/docs/en/contribution/release-java-agent.md @@ -276,7 +276,7 @@ export NAME=skywalking-java-agent export HUB=apache export TAG=$SW_VERSION -make docker.push.alpine docker.push.java8 docker.push.java11 docker.push.java17 docker.push.java21 +make docker.push.alpine docker.push.java8 docker.push.java11 docker.push.java17 docker.push.java21 docker.push.java25 ``` ## Clean up the old releases From 6594727c95501d8b090c365b67cb4b2bfc9698a8 Mon Sep 17 00:00:00 2001 From: wuwen Date: Mon, 23 Feb 2026 00:16:08 +0800 Subject: [PATCH 092/114] Change QTime condition from 'gt 0' to 'ge 0' (#793) --- .../solrj-7.x-scenario/config/expectedData.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/plugin/scenarios/solrj-7.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/solrj-7.x-scenario/config/expectedData.yaml index 3ff59ca319..93dd81f044 100644 --- a/test/plugin/scenarios/solrj-7.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/solrj-7.x-scenario/config/expectedData.yaml @@ -32,7 +32,7 @@ segmentItems: tags: - {key: db.type, value: Solr} - {key: http.status_code, value: '200'} - - {key: QTime, value: gt 0} + - {key: QTime, value: ge 0} skipAnalysis: 'false' - operationName: solrJ/mycore/update/COMMIT parentSpanId: 0 @@ -47,7 +47,7 @@ segmentItems: tags: - {key: db.type, value: Solr} - {key: http.status_code, value: '200'} - - {key: QTime, value: gt 0} + - {key: QTime, value: ge 0} skipAnalysis: 'false' - operationName: solrJ/mycore/update/OPTIMIZE parentSpanId: 0 @@ -62,7 +62,7 @@ segmentItems: tags: - {key: db.type, value: Solr} - {key: http.status_code, value: '200'} - - {key: QTime, value: gt 0} + - {key: QTime, value: ge 0} skipAnalysis: 'false' - operationName: solrJ/mycore/select parentSpanId: 0 @@ -111,7 +111,7 @@ segmentItems: tags: - {key: db.type, value: Solr} - {key: http.status_code, value: '200'} - - {key: QTime, value: gt 0} + - {key: QTime, value: ge 0} skipAnalysis: 'false' - operationName: solrJ/mycore/update/DELETE_BY_QUERY parentSpanId: 0 @@ -126,7 +126,7 @@ segmentItems: tags: - {key: db.type, value: Solr} - {key: http.status_code, value: '200'} - - {key: QTime, value: gt 0} + - {key: QTime, value: ge 0} skipAnalysis: 'false' - operationName: GET:/solrj-scenario/case/solrj parentSpanId: -1 From d22e51aedf82524a4ca3aeea3e4b7e9196c71b72 Mon Sep 17 00:00:00 2001 From: wuwen Date: Tue, 24 Feb 2026 14:15:47 +0800 Subject: [PATCH 093/114] Added support for Lettuce reactive Redis commands (#788) --- .github/workflows/plugins-jdk17-test.1.yaml | 1 + .github/workflows/plugins-test.1.yaml | 1 + CHANGES.md | 2 +- ...iveCreatePublisherMethodInterceptorV5.java | 89 ++++++++++++ ...edisReactiveCommandsInstrumentationV5.java | 89 ++++++++++++ .../src/main/resources/skywalking-plugin.def | 3 +- ...veCreatePublisherMethodInterceptorV65.java | 93 ++++++++++++ ...disReactiveCommandsInstrumentationV65.java | 89 ++++++++++++ .../src/main/resources/skywalking-plugin.def | 3 +- .../common/RedisChannelWriterInterceptor.java | 29 +++- .../RedisCommandCancelMethodInterceptor.java | 4 +- ...ompleteExceptionallyMethodInterceptor.java | 4 +- ...RedisCommandCompleteMethodInterceptor.java | 4 +- .../common/RedisCommandEnhanceInfo.java | 59 ++++++++ ...disSubscriptionConstructorInterceptor.java | 39 +++++ ...ubscriptionSubscribeMethodInterceptor.java | 61 ++++++++ .../RedisSubscriptionInstrumentation.java | 86 +++++++++++ .../src/main/resources/skywalking-plugin.def | 3 +- .../config/expectedData.yaml | 105 ++++++++++++++ .../lettuce/controller/LettuceController.java | 16 +++ .../lettuce-scenario/config/expectedData.yaml | 105 ++++++++++++++ .../lettuce/controller/LettuceController.java | 16 +++ .../bin/startup.sh | 21 +++ .../config/expectedData.yaml | 134 +++++++++++++++++ .../configuration.yml | 30 ++++ .../lettuce-webflux-5x-scenario/pom.xml | 98 +++++++++++++ .../src/main/assembly/assembly.xml | 41 ++++++ .../apm/testcase/lettuce/Application.java | 34 +++++ .../testcase/lettuce/RedisClientConfig.java | 37 +++++ .../controller/LettuceReactiveController.java | 68 +++++++++ .../src/main/resources/application.properties | 18 +++ .../src/main/resources/log4j2.xml | 30 ++++ .../support-version.list | 19 +++ .../bin/startup.sh | 21 +++ .../config/expectedData.yaml | 135 ++++++++++++++++++ .../configuration.yml | 30 ++++ .../lettuce-webflux-6x-scenario/pom.xml | 117 +++++++++++++++ .../src/main/assembly/assembly.xml | 41 ++++++ .../apm/testcase/lettuce/Application.java | 30 ++++ .../testcase/lettuce/RedisClientConfig.java | 37 +++++ .../controller/LettuceReactiveController.java | 63 ++++++++ .../src/main/resources/application.properties | 18 +++ .../support-version.list | 20 +++ 43 files changed, 1928 insertions(+), 15 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisReactiveCreatePublisherMethodInterceptorV5.java create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisReactiveCommandsInstrumentationV5.java create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisReactiveCreatePublisherMethodInterceptorV65.java create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisReactiveCommandsInstrumentationV65.java create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandEnhanceInfo.java create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionSubscribeMethodInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisSubscriptionInstrumentation.java create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/pom.xml create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/application.properties create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/pom.xml create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/application.properties create mode 100644 test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index 0aa6266813..939393713b 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -80,6 +80,7 @@ jobs: - c3p0-0.9.2.x-0.10.x-scenario - spring-scheduled-6.x-scenario - caffeine-3.x-scenario + - lettuce-webflux-6x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/plugins-test.1.yaml b/.github/workflows/plugins-test.1.yaml index 5b67f1d22d..21d5f04eab 100644 --- a/.github/workflows/plugins-test.1.yaml +++ b/.github/workflows/plugins-test.1.yaml @@ -88,6 +88,7 @@ jobs: - kotlin-coroutine-scenario - lettuce-scenario - lettuce-6.5.x-scenario + - lettuce-webflux-5x-scenario - mongodb-3.x-scenario - mongodb-4.x-scenario - netty-socketio-scenario diff --git a/CHANGES.md b/CHANGES.md index eaa28ff2c8..29acf896e1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,7 @@ Release Notes. 9.7.0 ------------------ - +* Added support for Lettuce reactive Redis commands. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisReactiveCreatePublisherMethodInterceptorV5.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisReactiveCreatePublisherMethodInterceptorV5.java new file mode 100644 index 0000000000..12ddea18f7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisReactiveCreatePublisherMethodInterceptorV5.java @@ -0,0 +1,89 @@ +/* + * 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.lettuce.v5; + +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.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.util.context.Context; + +import java.lang.reflect.Method; +import java.util.function.Function; + +/** + * Intercepts reactive publisher factory methods (createMono/createFlux) + * to ensure the SkyWalking context snapshot is propagated via Reactor Context. + * + *

If the Reactor Context does not already contain a snapshot, this interceptor + * captures the current active context and writes it into the subscriber context + * as a fallback propagation mechanism.

+ */ +public class RedisReactiveCreatePublisherMethodInterceptorV5 implements InstanceMethodsAroundInterceptorV2 { + + private static final String SNAPSHOT_KEY = "SKYWALKING_CONTEXT_SNAPSHOT"; + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInvocationContext context) { + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret, MethodInvocationContext context) { + + if (!(ret instanceof Mono) && !(ret instanceof Flux)) { + return ret; + } + final AbstractSpan localSpan = ContextManager.createLocalSpan("Lettuce/Reactive/" + method.getName()); + localSpan.setComponent(ComponentsDefine.LETTUCE); + SpanLayer.asCache(localSpan); + + try { + final ContextSnapshot snapshot = ContextManager.capture(); + + Function contextFunction = ctx -> { + if (ctx.hasKey(SNAPSHOT_KEY)) { + return ctx; + } + return ctx.put(SNAPSHOT_KEY, snapshot); + }; + + if (ret instanceof Mono) { + Mono original = (Mono) ret; + return original.subscriberContext(contextFunction); + } else { + Flux original = (Flux) ret; + return original.subscriberContext(contextFunction); + } + } finally { + ContextManager.stopSpan(); + } + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] + argumentsTypes, Throwable t, MethodInvocationContext context) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisReactiveCommandsInstrumentationV5.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisReactiveCommandsInstrumentationV5.java new file mode 100644 index 0000000000..65716edd68 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisReactiveCommandsInstrumentationV5.java @@ -0,0 +1,89 @@ +/* + * 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.lettuce.v5.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import java.util.Collections; +import java.util.List; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch; + +/** + * + */ +public class RedisReactiveCommandsInstrumentationV5 extends ClassInstanceMethodsEnhancePluginDefineV2 { + + private static final String ENHANCE_CLASS = "io.lettuce.core.AbstractRedisReactiveCommands"; + + private static final String REDIS_REACTIVE_CREATEMONO_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.v5.RedisReactiveCreatePublisherMethodInterceptorV5"; + + @Override + public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { + return new InstanceMethodsInterceptV2Point[]{ + new InstanceMethodsInterceptV2Point() { + @Override + public ElementMatcher getMethodsMatcher() { + return namedOneOf( + "createMono", + "createFlux", + "createDissolvingFlux" + ).and(takesArguments(1)); + } + + @Override + public String getMethodsInterceptorV2() { + return REDIS_REACTIVE_CREATEMONO_METHOD_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + public ClassMatch enhanceClass() { + return byHierarchyMatch(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + "reactor.core.publisher.Mono", + named("subscriberContext") + )); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def index 1ff563829d..006ef23680 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def @@ -14,4 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -lettuce-5.x-6.4.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisChannelWriterInstrumentationV5 \ No newline at end of file +lettuce-5.x-6.4.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisChannelWriterInstrumentationV5 +lettuce-5.x-6.4.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisReactiveCommandsInstrumentationV5 \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisReactiveCreatePublisherMethodInterceptorV65.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisReactiveCreatePublisherMethodInterceptorV65.java new file mode 100644 index 0000000000..36320b5cd1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisReactiveCreatePublisherMethodInterceptorV65.java @@ -0,0 +1,93 @@ +/* + * 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.lettuce.v65; + +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.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.reactivestreams.Publisher; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.lang.reflect.Method; + +/** + * Intercepts reactive publisher factory methods (createMono/createFlux) + * to ensure the SkyWalking context snapshot is propagated via Reactor Context. + * + *

If the Reactor Context does not already contain a snapshot, this interceptor + * captures the current active context and writes it into the subscriber context + * as a fallback propagation mechanism.

+ */ +public class RedisReactiveCreatePublisherMethodInterceptorV65 implements InstanceMethodsAroundInterceptorV2 { + + private static final String SNAPSHOT_KEY = "SKYWALKING_CONTEXT_SNAPSHOT"; + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInvocationContext context) { + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret, MethodInvocationContext context) { + + if (!(ret instanceof Mono) && !(ret instanceof Flux)) { + return ret; + } + + final AbstractSpan localSpan = ContextManager.createLocalSpan("Lettuce/Reactive/" + method.getName()); + localSpan.setComponent(ComponentsDefine.LETTUCE); + SpanLayer.asCache(localSpan); + + try { + final ContextSnapshot snapshot = ContextManager.capture(); + + return wrapPublisher((Publisher) ret, snapshot); + } finally { + ContextManager.stopSpan(); + } + } + + private Publisher wrapPublisher(Publisher original, ContextSnapshot snapshot) { + if (original instanceof Mono) { + return Mono.deferContextual(ctxView -> { + if (ctxView.hasKey(SNAPSHOT_KEY)) { + return (Mono) original; + } + return ((Mono) original).contextWrite(c -> c.put(SNAPSHOT_KEY, snapshot)); + }); + } else { + return Flux.deferContextual(ctxView -> { + if (ctxView.hasKey(SNAPSHOT_KEY)) { + return original; + } + return ((Flux) original).contextWrite(c -> c.put(SNAPSHOT_KEY, snapshot)); + }); + } + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisReactiveCommandsInstrumentationV65.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisReactiveCommandsInstrumentationV65.java new file mode 100644 index 0000000000..f1c22b88ee --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisReactiveCommandsInstrumentationV65.java @@ -0,0 +1,89 @@ +/* + * 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.lettuce.v65.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.WitnessMethod; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import java.util.Collections; +import java.util.List; + +import static net.bytebuddy.matcher.ElementMatchers.namedOneOf; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch; + +/** + * + */ +public class RedisReactiveCommandsInstrumentationV65 extends ClassInstanceMethodsEnhancePluginDefineV2 { + + private static final String ENHANCE_CLASS = "io.lettuce.core.AbstractRedisReactiveCommands"; + + private static final String REDIS_REACTIVE_CREATEMONO_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.v65.RedisReactiveCreatePublisherMethodInterceptorV65"; + + @Override + public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { + return new InstanceMethodsInterceptV2Point[]{ + new InstanceMethodsInterceptV2Point() { + @Override + public ElementMatcher getMethodsMatcher() { + return namedOneOf( + "createMono", + "createFlux", + "createDissolvingFlux" + ).and(takesArguments(1)); + } + + @Override + public String getMethodsInterceptorV2() { + return REDIS_REACTIVE_CREATEMONO_METHOD_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + public ClassMatch enhanceClass() { + return byHierarchyMatch(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + "reactor.core.publisher.Mono", + ElementMatchers.named("deferContextual") + )); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def index a503891244..aac68f9479 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def @@ -14,4 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65 \ No newline at end of file +lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65 +lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisReactiveCommandsInstrumentationV65 \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java index f8b66f1349..9a94e186d8 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java @@ -57,12 +57,17 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } EnhancedInstance enhancedCommand = (EnhancedInstance) spanCarrierCommand; + RedisCommandEnhanceInfo redisCommandEnhanceInfo = (RedisCommandEnhanceInfo) enhancedCommand.getSkyWalkingDynamicField(); + + if (redisCommandEnhanceInfo == null) { + redisCommandEnhanceInfo = new RedisCommandEnhanceInfo(); + } + // command has been handle by another channel writer (cluster or sentinel case) - if (enhancedCommand.getSkyWalkingDynamicField() != null) { + if (redisCommandEnhanceInfo.getSpan() != null) { //set peer in last channel writer (delegate) if (peer != null) { - AbstractSpan span = (AbstractSpan) enhancedCommand.getSkyWalkingDynamicField(); - span.setPeer(peer); + redisCommandEnhanceInfo.getSpan().setPeer(peer); } return; } @@ -81,7 +86,16 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr operationName = operationName + "BATCH_WRITE"; command = "BATCH_WRITE"; } + + if (redisCommandEnhanceInfo.getSnapshot() != null) { + AbstractSpan localSpan = ContextManager.createLocalSpan("RedisReactive/local"); + localSpan.setComponent(ComponentsDefine.LETTUCE); + SpanLayer.asCache(localSpan); + ContextManager.continued(redisCommandEnhanceInfo.getSnapshot()); + } + AbstractSpan span = ContextManager.createExitSpan(operationName, peer); + span.setComponent(ComponentsDefine.LETTUCE); Tags.CACHE_TYPE.set(span, "Redis"); if (StringUtil.isNotEmpty(key)) { @@ -92,7 +106,12 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr SpanLayer.asCache(span); span.prepareForAsync(); ContextManager.stopSpan(); - enhancedCommand.setSkyWalkingDynamicField(span); + + if (redisCommandEnhanceInfo.getSnapshot() != null) { + ContextManager.stopSpan(); + } + + enhancedCommand.setSkyWalkingDynamicField(redisCommandEnhanceInfo.setSpan(span)); } private String getArgsKey(RedisCommand redisCommand) { @@ -124,7 +143,7 @@ public void handleMethodException(EnhancedInstance objInst, Method method, Objec RedisCommand redisCommand = getSpanCarrierCommand(allArguments[0]); if (redisCommand instanceof EnhancedInstance && ((EnhancedInstance) redisCommand).getSkyWalkingDynamicField() != null) { EnhancedInstance enhancedRedisCommand = (EnhancedInstance) redisCommand; - AbstractSpan abstractSpan = (AbstractSpan) enhancedRedisCommand.getSkyWalkingDynamicField(); + AbstractSpan abstractSpan = ((RedisCommandEnhanceInfo) enhancedRedisCommand.getSkyWalkingDynamicField()).getSpan(); enhancedRedisCommand.setSkyWalkingDynamicField(null); abstractSpan.log(t); abstractSpan.asyncFinish(); diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java index 7fb9f3c943..82f4d6e55d 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java @@ -37,7 +37,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) { if (objInst.getSkyWalkingDynamicField() != null) { - AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField(); + AbstractSpan span = ((RedisCommandEnhanceInfo) objInst.getSkyWalkingDynamicField()).getSpan(); span.errorOccurred(); span.tag(new StringTag(CANCEL_SIGNAL_TAG), COMMAND_CANCEL_VALUE); span.asyncFinish(); @@ -49,7 +49,7 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { if (objInst.getSkyWalkingDynamicField() != null) { - AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField(); + AbstractSpan span = ((RedisCommandEnhanceInfo) objInst.getSkyWalkingDynamicField()).getSpan(); span.log(t); } } diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java index bdde0712df..022c2622ee 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java @@ -35,7 +35,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) { if (objInst.getSkyWalkingDynamicField() != null) { Throwable t = (Throwable) allArguments[0]; - AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField(); + AbstractSpan span = ((RedisCommandEnhanceInfo) objInst.getSkyWalkingDynamicField()).getSpan(); span.log(t); span.asyncFinish(); objInst.setSkyWalkingDynamicField(null); @@ -46,7 +46,7 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { if (objInst.getSkyWalkingDynamicField() != null) { - AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField(); + AbstractSpan span = ((RedisCommandEnhanceInfo) objInst.getSkyWalkingDynamicField()).getSpan(); span.log(t); } } diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java index d2ede33ba7..725f2742bd 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java @@ -34,7 +34,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) { if (objInst.getSkyWalkingDynamicField() != null) { - AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField(); + AbstractSpan span = ((RedisCommandEnhanceInfo) objInst.getSkyWalkingDynamicField()).getSpan(); span.asyncFinish(); objInst.setSkyWalkingDynamicField(null); } @@ -45,7 +45,7 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { if (objInst.getSkyWalkingDynamicField() != null) { - AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField(); + AbstractSpan span = ((RedisCommandEnhanceInfo) objInst.getSkyWalkingDynamicField()).getSpan(); span.log(t); } } diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandEnhanceInfo.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandEnhanceInfo.java new file mode 100644 index 0000000000..942d5e18f4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandEnhanceInfo.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.lettuce.common; + +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; + +/** + * RedisCommandEnhanceInfo holds SkyWalking tracing data for Lettuce commands + * executed in different asynchronous models. + * + *

The {@link AbstractSpan} is used for non-reactive (blocking) commands + * that are executed asynchronously, where the span needs to be created + * at command submission time and finished when the command completes.

+ * + *

The {@link ContextSnapshot} is used for reactive commands, where the + * tracing context is captured from Reactor {@code Context} and later + * continued at subscription or execution time to bridge reactive + * boundaries.

+ */ +class RedisCommandEnhanceInfo { + + private AbstractSpan span; + private ContextSnapshot snapshot; + + public AbstractSpan getSpan() { + return span; + } + + public RedisCommandEnhanceInfo setSpan(AbstractSpan span) { + this.span = span; + return this; + } + + public ContextSnapshot getSnapshot() { + return snapshot; + } + + public RedisCommandEnhanceInfo setSnapshot(ContextSnapshot snapshot) { + this.snapshot = snapshot; + return this; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionConstructorInterceptor.java new file mode 100644 index 0000000000..7c79ebde93 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionConstructorInterceptor.java @@ -0,0 +1,39 @@ +/* + * 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.lettuce.common; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +/** + * Interceptor for RedisSubscription constructor. + *

+ * This interceptor captures the {@link io.lettuce.core.protocol.RedisCommand} instance + * at subscription construction time and stores it into SkyWalking dynamic field. + *

+ */ +public class RedisSubscriptionConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + // allArguments[1] is the RedisCommand passed to the RedisSubscription constructor + objInst.setSkyWalkingDynamicField(allArguments[1]); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionSubscribeMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionSubscribeMethodInterceptor.java new file mode 100644 index 0000000000..0ea108a247 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionSubscribeMethodInterceptor.java @@ -0,0 +1,61 @@ +/* + * 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.lettuce.common; + +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext; +import reactor.core.CoreSubscriber; + +import java.lang.reflect.Method; + +/** + * Interceptor for {@code RedisPublisher.RedisSubscription#subscribe(Subscriber)} method. + * + *

+ * This interceptor works together with the constructor interceptor of + * {@code RedisSubscription}: + *

+ */ +public class RedisSubscriptionSubscribeMethodInterceptor implements InstanceMethodsAroundInterceptorV2 { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInvocationContext context) { + if (allArguments[0] instanceof CoreSubscriber) { + CoreSubscriber subscriber = (CoreSubscriber) allArguments[0]; + // get ContextSnapshot from reactor context, the snapshot is set to reactor context by any other plugin + // such as DispatcherHandlerHandleMethodInterceptor in spring-webflux-5.x-plugin + Object skywalkingContextSnapshot = subscriber.currentContext().getOrDefault("SKYWALKING_CONTEXT_SNAPSHOT", null); + if (skywalkingContextSnapshot != null) { + ((EnhancedInstance) objInst.getSkyWalkingDynamicField()).setSkyWalkingDynamicField(new RedisCommandEnhanceInfo() + .setSnapshot((ContextSnapshot) skywalkingContextSnapshot)); + } + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret, MethodInvocationContext context) { + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisSubscriptionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisSubscriptionInstrumentation.java new file mode 100644 index 0000000000..7e7ccc7632 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisSubscriptionInstrumentation.java @@ -0,0 +1,86 @@ +/* + * 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.lettuce.common.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.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * + */ +public class RedisSubscriptionInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 { + + private static final String ENHANCE_CLASS = "io.lettuce.core.RedisPublisher$RedisSubscription"; + + private static final String REDIS_SUBSCRIPTION_SUBSCRIBE_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.common.RedisSubscriptionSubscribeMethodInterceptor"; + private static final String REDIS_SUBSCRIPTION_CONST_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.common.RedisSubscriptionConstructorInterceptor"; + + @Override + public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { + return new InstanceMethodsInterceptV2Point[]{ + new InstanceMethodsInterceptV2Point() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("subscribe"); + } + + @Override + public String getMethodsInterceptorV2() { + return REDIS_SUBSCRIPTION_SUBSCRIBE_METHOD_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any().and(takesArgument(1, named("io.lettuce.core.protocol.RedisCommand"))); + } + + @Override + public String getConstructorInterceptor() { + return REDIS_SUBSCRIPTION_CONST_METHOD_INTERCEPTOR; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def index e0521938a7..e17d02461c 100644 --- a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def @@ -15,4 +15,5 @@ # limitations under the License. lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.DefaultEndpointInstrumentation -lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.RedisCommandInstrumentation \ No newline at end of file +lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.RedisCommandInstrumentation +lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.RedisSubscriptionInstrumentation \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml index 2a938caea9..dbeb6b6138 100644 --- a/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml @@ -34,6 +34,60 @@ segmentItems: - {key: url, value: 'http://localhost:8080/lettuce-6.5.x-scenario/case/healthCheck'} - {key: http.method, value: HEAD} - {key: http.status_code, value: '200'} + - segmentId: not null + spans: + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key0 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: GET:/lettuce-6.5.x-scenario/case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 5, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + - segmentId: not null + spans: + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key1 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: GET:/lettuce-6.5.x-scenario/case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 6, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } - segmentId: not null spans: - operationName: Lettuce/GET @@ -84,6 +138,57 @@ segmentItems: - { key: cache.key, value: key1 } - { key: cache.cmd, value: SET } - { key: cache.op, value: write } + - operationName: Lettuce/Reactive/createMono + parentSpanId: 0 + spanId: 4 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Local + skipAnalysis: false + - operationName: Lettuce/Reactive/createMono + parentSpanId: 0 + spanId: 5 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Local + skipAnalysis: false + - operationName: Lettuce/Reactive/createMono + parentSpanId: 0 + spanId: 6 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Local + skipAnalysis: false + - operationName: Lettuce/GET + parentSpanId: 7 + spanId: 8 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key } + - { key: cache.cmd, value: GET } + - { key: cache.op, value: read } + - operationName: RedisReactive/local + parentSpanId: 0 + spanId: 7 + isError: false + spanType: Local - operationName: GET:/lettuce-6.5.x-scenario/case/lettuce-case parentSpanId: -1 spanId: 0 diff --git a/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java index c2f391b07c..d2cc201025 100644 --- a/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java +++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java @@ -23,6 +23,7 @@ import io.lettuce.core.RedisFuture; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.async.RedisAsyncCommands; +import io.lettuce.core.api.reactive.RedisReactiveCommands; import io.lettuce.core.api.sync.RedisCommands; import java.util.ArrayList; import java.util.List; @@ -32,6 +33,8 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; @Controller @RequestMapping("/case") @@ -58,8 +61,21 @@ public String lettuceCase() { asyncCommands.flushCommands(); LettuceFutures.awaitAll(5, TimeUnit.SECONDS, futures.toArray(new RedisFuture[futures.size()])); + StatefulRedisConnection connection2 = redisClient.connect(); + RedisReactiveCommands reactiveCommands = connection2.reactive(); + + Mono result = reactiveCommands.get("key") + .then(Flux.concat( + reactiveCommands.set("key0", "value0"), + reactiveCommands.set("key1", "value1") + ).then()) + .thenReturn("Success"); + + result.block(); + connection0.close(); connection1.close(); + connection2.close(); redisClient.shutdown(); return "Success"; } diff --git a/test/plugin/scenarios/lettuce-scenario/config/expectedData.yaml b/test/plugin/scenarios/lettuce-scenario/config/expectedData.yaml index 43db792872..884191cfe3 100644 --- a/test/plugin/scenarios/lettuce-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/lettuce-scenario/config/expectedData.yaml @@ -34,6 +34,60 @@ segmentItems: - {key: url, value: 'http://localhost:8080/lettuce-scenario/case/healthCheck'} - {key: http.method, value: HEAD} - {key: http.status_code, value: '200'} + - segmentId: not null + spans: + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key0 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: GET:/lettuce-scenario/case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 5, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + - segmentId: not null + spans: + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key1 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: GET:/lettuce-scenario/case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 6, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } - segmentId: not null spans: - operationName: Lettuce/GET @@ -84,6 +138,57 @@ segmentItems: - { key: cache.key, value: key1 } - { key: cache.cmd, value: SET } - { key: cache.op, value: write } + - operationName: Lettuce/Reactive/createMono + parentSpanId: 0 + spanId: 4 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Local + skipAnalysis: false + - operationName: Lettuce/Reactive/createMono + parentSpanId: 0 + spanId: 5 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Local + skipAnalysis: false + - operationName: Lettuce/Reactive/createMono + parentSpanId: 0 + spanId: 6 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Local + skipAnalysis: false + - operationName: Lettuce/GET + parentSpanId: 7 + spanId: 8 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key } + - { key: cache.cmd, value: GET } + - { key: cache.op, value: read } + - operationName: RedisReactive/local + parentSpanId: 0 + spanId: 7 + isError: false + spanType: Local - operationName: GET:/lettuce-scenario/case/lettuce-case parentSpanId: -1 spanId: 0 diff --git a/test/plugin/scenarios/lettuce-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java b/test/plugin/scenarios/lettuce-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java index c2f391b07c..d2cc201025 100644 --- a/test/plugin/scenarios/lettuce-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java +++ b/test/plugin/scenarios/lettuce-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java @@ -23,6 +23,7 @@ import io.lettuce.core.RedisFuture; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.async.RedisAsyncCommands; +import io.lettuce.core.api.reactive.RedisReactiveCommands; import io.lettuce.core.api.sync.RedisCommands; import java.util.ArrayList; import java.util.List; @@ -32,6 +33,8 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; @Controller @RequestMapping("/case") @@ -58,8 +61,21 @@ public String lettuceCase() { asyncCommands.flushCommands(); LettuceFutures.awaitAll(5, TimeUnit.SECONDS, futures.toArray(new RedisFuture[futures.size()])); + StatefulRedisConnection connection2 = redisClient.connect(); + RedisReactiveCommands reactiveCommands = connection2.reactive(); + + Mono result = reactiveCommands.get("key") + .then(Flux.concat( + reactiveCommands.set("key0", "value0"), + reactiveCommands.set("key1", "value1") + ).then()) + .thenReturn("Success"); + + result.block(); + connection0.close(); connection1.close(); + connection2.close(); redisClient.shutdown(); return "Success"; } diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/bin/startup.sh b/test/plugin/scenarios/lettuce-webflux-5x-scenario/bin/startup.sh new file mode 100644 index 0000000000..d719f14162 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-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 -Dredis.host=${REDIS_SERVERS} -jar -Dskywalking.plugin.lettuce.trace_redis_parameters=true ${agent_opts} ${home}/../libs/lettuce-webflux-5x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/config/expectedData.yaml b/test/plugin/scenarios/lettuce-webflux-5x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..cdc04a6242 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/config/expectedData.yaml @@ -0,0 +1,134 @@ +# 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: lettuce-webflux-5x-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: /case/healthCheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 67 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/case/healthCheck'} + - {key: http.method, value: HEAD} + - {key: http.status_code, value: '200'} + - segmentId: not null + spans: + - operationName: Lettuce/GET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: cache.type, value: Redis} + - {key: cache.key, value: key} + - {key: cache.cmd, value: GET} + - {key: cache.op, value: read} + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: /case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + - segmentId: not null + spans: + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key0 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: /case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + - segmentId: not null + spans: + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key1 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: /case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + - segmentId: not null + spans: + - operationName: /case/lettuce-case + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 67 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/case/lettuce-case'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml b/test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml new file mode 100644 index 0000000000..d016d55400 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml @@ -0,0 +1,30 @@ +# 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/case/lettuce-case +healthCheck: http://localhost:8080/case/healthCheck +startScript: ./bin/startup.sh +withPlugins: apm-spring-webflux-5.x-*.jar +runningMode: with_optional +environment: + - REDIS_SERVERS=redis-server:6379 +depends_on: + - redis-server +dependencies: + redis-server: + image: redis:3.2.9-alpine + hostname: redis-server diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/pom.xml b/test/plugin/scenarios/lettuce-webflux-5x-scenario/pom.xml new file mode 100644 index 0000000000..bf393539a2 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/pom.xml @@ -0,0 +1,98 @@ + + + + 4.0.0 + + org.apache.skywalking + lettuce-webflux-5x-scenario + 5.0.0 + + + UTF-8 + 1.8 + 3.8.1 + 5.1.8.RELEASE + ${test.framework.version} + 2.1.6.RELEASE + + + skywalking-lettuce-webflux-5x-scenario + + + + io.lettuce + lettuce-core + ${test.framework.version} + + + + org.springframework.boot + spring-boot-starter-webflux + ${spring.boot.version} + + + + + lettuce-webflux-5x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${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/lettuce-webflux-5x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..ffc45011aa --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/lettuce-webflux-5x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java new file mode 100644 index 0000000000..dae1948397 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java @@ -0,0 +1,34 @@ +/* + * 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.testcase.lettuce; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } +} diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java new file mode 100644 index 0000000000..0898d08338 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java @@ -0,0 +1,37 @@ +/* + * 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.testcase.lettuce; + +import io.lettuce.core.RedisClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * + */ +@Configuration +public class RedisClientConfig { + + @Bean(destroyMethod = "shutdown") + public RedisClient redisClient(@Value("${redis.servers:127.0.0.1:6379}") String address) { + + return RedisClient.create("redis://" + address); + } +} diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java new file mode 100644 index 0000000000..2664bd2713 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java @@ -0,0 +1,68 @@ +/* + * 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.testcase.lettuce.controller; + +import io.lettuce.core.RedisClient; +import io.lettuce.core.api.reactive.RedisReactiveCommands; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import javax.annotation.Resource; + +@RestController +@RequestMapping("/case") +@PropertySource("classpath:application.properties") +public class LettuceReactiveController { + + @Value("${redis.servers:127.0.0.1:6379}") + private String address; + + @Resource + private RedisClient redisClient; + + @GetMapping("/lettuce-case") + public Mono lettuceCase() { + + return Mono.usingWhen( + Mono.fromCallable(() -> redisClient.connect()), + connection -> { + RedisReactiveCommands cmd = connection.reactive(); + return cmd.get("key") + .then(Flux.concat( + cmd.set("key0", "value0"), + cmd.set("key1", "value1") + ).then()) + .thenReturn("Success"); + }, + connection -> Mono.fromFuture(connection.closeAsync()), + connection -> Mono.fromFuture(connection.closeAsync()), + connection -> Mono.fromFuture(connection.closeAsync()) + ); + } + + @GetMapping("/healthCheck") + public Mono healthCheck() { + return Mono.just("healthCheck"); + } +} diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/application.properties b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/application.properties new file mode 100644 index 0000000000..d3b193de12 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/application.properties @@ -0,0 +1,18 @@ +# +# 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/lettuce-webflux-5x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list b/test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list new file mode 100644 index 0000000000..a7e848bbbf --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list @@ -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. + +5.1.8.RELEASE +5.2.1.RELEASE +6.1.4.RELEASE \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/bin/startup.sh b/test/plugin/scenarios/lettuce-webflux-6x-scenario/bin/startup.sh new file mode 100644 index 0000000000..686b12f52a --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-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 -Dredis.host=${REDIS_SERVERS} -jar -Dskywalking.plugin.lettuce.trace_redis_parameters=true ${agent_opts} ${home}/../libs/lettuce-webflux-6x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/config/expectedData.yaml b/test/plugin/scenarios/lettuce-webflux-6x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..e5857aa054 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/config/expectedData.yaml @@ -0,0 +1,135 @@ +# 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: lettuce-webflux-6x-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: /case/healthCheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 67 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - { key: url, value: 'http://localhost:8080/case/healthCheck' } + - { key: http.method, value: HEAD } + - { key: http.status_code, value: '200' } + - segmentId: not null + spans: + - operationName: Lettuce/GET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key } + - { key: cache.cmd, value: GET } + - { key: cache.op, value: read } + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: /case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + - segmentId: not null + spans: + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key0 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: /case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + - segmentId: not null + spans: + - operationName: Lettuce/SET + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: not null + endTime: not null + componentId: 57 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - { key: cache.type, value: Redis } + - { key: cache.key, value: key1 } + - { key: cache.cmd, value: SET } + - { key: cache.op, value: write } + - operationName: RedisReactive/local + parentSpanId: -1 + spanId: 0 + isError: false + spanType: Local + refs: + - { parentEndpoint: /case/lettuce-case, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null } + - segmentId: not null + spans: + - operationName: /case/lettuce-case + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 67 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - { key: url, value: 'http://localhost:8080/case/lettuce-case' } + - { key: http.method, value: GET } + - { key: http.status_code, value: '200' } + \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml b/test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml new file mode 100644 index 0000000000..a3eecec7bb --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml @@ -0,0 +1,30 @@ +# 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/case/lettuce-case +healthCheck: http://localhost:8080/case/healthCheck +startScript: ./bin/startup.sh +withPlugins: apm-spring-webflux-6.x-*.jar +runningMode: with_optional +environment: + - REDIS_SERVERS=redis-server:6379 +depends_on: + - redis-server +dependencies: + redis-server: + image: redis:3.2.9-alpine + hostname: redis-server diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/pom.xml b/test/plugin/scenarios/lettuce-webflux-6x-scenario/pom.xml new file mode 100644 index 0000000000..2e05615440 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/pom.xml @@ -0,0 +1,117 @@ + + + + 4.0.0 + + org.apache.skywalking + lettuce-webflux-6x-scenario + 5.0.0 + + + UTF-8 + 17 + 3.8.1 + 6.4.2.RELEASE + ${test.framework.version} + 3.0.13 + + + skywalking-lettuce-webflux-6x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + io.lettuce + lettuce-core + ${test.framework.version} + + + + org.springframework.boot + spring-boot-starter-webflux + ${spring.boot.version} + + + org.apache.logging.log4j + log4j-api + + + + + + + + lettuce-webflux-6x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${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/lettuce-webflux-6x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..87c9882cab --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/lettuce-webflux-6x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java new file mode 100644 index 0000000000..f96b624013 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java @@ -0,0 +1,30 @@ +/* + * 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.testcase.lettuce; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java new file mode 100644 index 0000000000..0898d08338 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java @@ -0,0 +1,37 @@ +/* + * 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.testcase.lettuce; + +import io.lettuce.core.RedisClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * + */ +@Configuration +public class RedisClientConfig { + + @Bean(destroyMethod = "shutdown") + public RedisClient redisClient(@Value("${redis.servers:127.0.0.1:6379}") String address) { + + return RedisClient.create("redis://" + address); + } +} diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java new file mode 100644 index 0000000000..697369fcf8 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java @@ -0,0 +1,63 @@ +/* + * 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.testcase.lettuce.controller; + +import io.lettuce.core.RedisClient; +import io.lettuce.core.api.reactive.RedisReactiveCommands; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +@RestController +@RequestMapping("/case") +public class LettuceReactiveController { + + @Value("${redis.servers:127.0.0.1:6379}") + private String address; + + @Autowired + private RedisClient redisClient; + + @GetMapping("/lettuce-case") + public Mono lettuceCase() { + + return Mono.usingWhen( + Mono.fromCallable(() -> redisClient.connect()), + connection -> { + RedisReactiveCommands cmd = connection.reactive(); + return cmd.get("key") + .then(Flux.concat( + cmd.set("key0", "value0"), + cmd.set("key1", "value1") + ).then()) + .thenReturn("Success"); + }, + connection -> Mono.fromFuture(connection.closeAsync()) + ); + } + + @GetMapping("/healthCheck") + public Mono healthCheck() { + return Mono.just("healthCheck"); + } +} diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/application.properties b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/application.properties new file mode 100644 index 0000000000..afdb52cef7 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/application.properties @@ -0,0 +1,18 @@ +# +# 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 \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list b/test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list new file mode 100644 index 0000000000..2cba7f3294 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list @@ -0,0 +1,20 @@ +# 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. + +6.4.2.RELEASE +6.5.5.RELEASE +6.6.0.RELEASE +6.7.1.RELEASE \ No newline at end of file From 0bab19b41dedc21528d71466b92484bc132f09fe Mon Sep 17 00:00:00 2001 From: wuwen Date: Tue, 24 Feb 2026 19:21:49 +0800 Subject: [PATCH 094/114] Update fallback retry delay in .dlc.json (#794) --- .dlc.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.dlc.json b/.dlc.json index 168494a4c4..483a8c1255 100644 --- a/.dlc.json +++ b/.dlc.json @@ -29,12 +29,15 @@ }, { "pattern": "^https://blogs.oracle.com/javamagazine/post/a-peek-into-java-17-continuing-the-drive-to-encapsulate-the-java-runtime-internals" + }, + { + "pattern": "^https://www.oceanbase.com/" } ], "timeout": "10s", "retryOn429": true, "retryCount": 10, - "fallbackRetryDelay": "1000s", + "fallbackRetryDelay": "60s", "aliveStatusCodes": [ 200, 301, From f750006020249d29a21cae63ae50da67f182c6ab Mon Sep 17 00:00:00 2001 From: peachisai <2581009893@qq.com> Date: Sun, 1 Mar 2026 23:07:40 +0800 Subject: [PATCH 095/114] Add Spring AI 1.x plugin and GenAI layer. (#795) --- .github/workflows/plugins-jdk17-test.0.yaml | 1 + CHANGES.md | 1 + .../trace/component/ComponentsDefine.java | 30 ++ apm-protocol/apm-network/src/main/proto | 2 +- .../apm/agent/core/context/tag/Tags.java | 90 ++++++ .../agent/core/context/trace/SpanLayer.java | 7 +- .../apm/agent/core/util/GsonUtil.java | 36 +++ .../apm-sdk-plugin/spring-plugins/pom.xml | 1 + .../spring-ai-1.x-plugin/pom.xml | 47 +++ .../ai/v1/ChatModelCallInterceptor.java | 179 ++++++++++++ .../ai/v1/ChatModelStreamInterceptor.java | 266 +++++++++++++++++ .../DefaultToolCallingManagerInterceptor.java | 63 ++++ .../ai/v1/ToolCallbackCallInterceptor.java | 79 +++++ .../v1/common/ChatModelMetadataResolver.java | 147 ++++++++++ .../ai/v1/config/SpringAiPluginConfig.java | 74 +++++ .../spring/ai/v1/contant/Constants.java | 31 ++ .../v1/define/ChatModelInstrumentation.java | 92 ++++++ ...aultToolCallingManagerInstrumentation.java | 72 +++++ .../define/ToolCallbackInstrumentation.java | 73 +++++ .../provider/AnthropicApiInstrumentation.java | 64 +++++ .../provider/DeepSeekApiInstrumentation.java | 64 +++++ .../HuggingfaceChatModelInstrumentation.java | 64 +++++ .../provider/MiniMaxApiInstrumentation.java | 64 +++++ .../provider/MistralAiApiInstrumentation.java | 64 +++++ .../provider/OllamaApiInstrumentation.java | 64 +++++ .../provider/OpenAiApiInstrumentation.java | 64 +++++ .../provider/ZhiPuAiApiInstrumentation.java | 64 +++++ .../spring/ai/v1/enums/AiProviderEnum.java | 68 +++++ .../spring/ai/v1/messages/InputMessages.java | 271 ++++++++++++++++++ .../spring/ai/v1/messages/OutputMessages.java | 121 ++++++++ .../AnthropicApiConstructorInterceptor.java | 38 +++ .../DeepSeekApiConstructorInterceptor.java | 38 +++ ...ngfaceChatModelConstructorInterceptor.java | 37 +++ .../MiniMaxApiConstructorInterceptor.java | 38 +++ .../MistralAiApiConstructorInterceptor.java | 40 +++ .../OllamaApiConstructorInterceptor.java | 38 +++ .../OpenAiApiConstructorInterceptor.java | 38 +++ .../ZhiPuAiApiConstructorInterceptor.java | 38 +++ .../src/main/resources/skywalking-plugin.def | 27 ++ apm-sniffer/config/agent.config | 22 ++ .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 2 + pom.xml | 2 +- test/plugin/agent-test-tools/pom.xml | 2 +- .../support-version.list | 2 +- .../rocketmq-scenario/support-version.list | 4 +- .../spring-ai-1.x-scenario/bin/startup.sh | 21 ++ .../config/expectedData.yaml | 156 ++++++++++ .../spring-ai-1.x-scenario/configuration.yml | 21 ++ .../scenarios/spring-ai-1.x-scenario/pom.xml | 156 ++++++++++ .../src/main/assembly/assembly.xml | 41 +++ .../testcase/jdk/httpclient/Application.java | 30 ++ .../httpclient/config/ChatClientConfig.java | 32 +++ .../httpclient/controller/CaseController.java | 68 +++++ .../controller/LLMMockController.java | 230 +++++++++++++++ .../jdk/httpclient/tool/WeatherTool.java | 33 +++ .../src/main/resources/application.yaml | 35 +++ .../support-version.list | 18 ++ 58 files changed, 3464 insertions(+), 7 deletions(-) create mode 100644 apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/GsonUtil.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/DefaultToolCallingManagerInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ToolCallbackCallInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/ChatModelMetadataResolver.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/contant/Constants.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/ChatModelInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/DefaultToolCallingManagerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/ToolCallbackInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/AnthropicApiInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/DeepSeekApiInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/HuggingfaceChatModelInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/MiniMaxApiInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/MistralAiApiInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/OllamaApiInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/OpenAiApiInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/ZhiPuAiApiInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/enums/AiProviderEnum.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/InputMessages.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/OutputMessages.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/AnthropicApiConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/DeepSeekApiConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/HuggingfaceChatModelConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/MiniMaxApiConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/MistralAiApiConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/OllamaApiConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/OpenAiApiConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/ZhiPuAiApiConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/Application.java create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/config/ChatClientConfig.java create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/LLMMockController.java create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/tool/WeatherTool.java create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/spring-ai-1.x-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk17-test.0.yaml b/.github/workflows/plugins-jdk17-test.0.yaml index cfec09ac3c..092fa2daae 100644 --- a/.github/workflows/plugins-jdk17-test.0.yaml +++ b/.github/workflows/plugins-jdk17-test.0.yaml @@ -79,6 +79,7 @@ jobs: - grizzly-2.3.x-4.x-workthreadpool-scenario - jetty-11.x-scenario - jetty-10.x-scenario + - spring-ai-1.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 29acf896e1..27e5c01fde 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Release Notes. ------------------ * Added support for Lettuce reactive Redis commands. +* Add Spring AI 1.x plugin and GenAI layer. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index fa62c91239..a8b57ba7f8 100755 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -265,4 +265,34 @@ public class ComponentsDefine { public static final OfficialComponent DMDB_JDBC_DRIVER = new OfficialComponent(163, "Dmdb-jdbc-driver"); + public static final OfficialComponent SPRING_AI_UNKNOWN = new OfficialComponent(164, "spring-ai-unknown"); + + public static final OfficialComponent SPRING_AI_ANTHROPIC = new OfficialComponent(165, "spring-ai-anthropic"); + + public static final OfficialComponent SPRING_AI_BEDROCK = new OfficialComponent(166, "spring-ai-aws-bedrock"); + + public static final OfficialComponent SPRING_AI_AZURE_OPENAI = new OfficialComponent(167, "spring-ai-azure-openai"); + + public static final OfficialComponent SPRING_AI_COHERE = new OfficialComponent(168, "spring-ai-cohere"); + + public static final OfficialComponent SPRING_AI_DEEPSEEK = new OfficialComponent(169, "spring-ai-deepseek"); + + public static final OfficialComponent SPRING_AI_GOOGLE_GENAI = new OfficialComponent(170, "spring-ai-gcp-genai"); + + public static final OfficialComponent SPRING_AI_VERTEXAI = new OfficialComponent(171, "spring-ai-gcp-vertex-ai"); + + public static final OfficialComponent SPRING_AI_MISTRAL_AI = new OfficialComponent(172, "spring-ai-mistral-ai"); + + public static final OfficialComponent SPRING_AI_OPENAI = new OfficialComponent(173, "spring-ai-openai"); + + public static final OfficialComponent SPRING_AI_HUGGINGFACE = new OfficialComponent(174, "spring-ai-huggingface"); + + public static final OfficialComponent SPRING_AI_MINIMAX = new OfficialComponent(175, "spring-ai-minimax"); + + public static final OfficialComponent SPRING_AI_OLLAMA = new OfficialComponent(176, "spring-ai-ollama"); + + public static final OfficialComponent SPRING_AI_ZHIPU_AI = new OfficialComponent(177, "spring-ai-zhipu-ai"); + + public static final OfficialComponent SPRING_AI = new OfficialComponent(178, "spring-ai"); + } diff --git a/apm-protocol/apm-network/src/main/proto b/apm-protocol/apm-network/src/main/proto index 16c51358eb..07882d57be 160000 --- a/apm-protocol/apm-network/src/main/proto +++ b/apm-protocol/apm-network/src/main/proto @@ -1 +1 @@ -Subproject commit 16c51358ebcf42629bf4ffdf952253971f20eb25 +Subproject commit 07882d57becb37e341f7fc492c11f9f5a5f311cf diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java index 18093a453e..995b91f582 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java @@ -160,6 +160,96 @@ public static final class HTTP { */ public static final StringTag THREAD_CARRIER = new StringTag(24, "thread.carrier"); + /** + * GEN_AI_OPERATION_NAME represents the name of the operation being performed + */ + public static final StringTag GEN_AI_OPERATION_NAME = new StringTag(25, "gen_ai.operation.name"); + + /** + * GEN_AI_PROVIDER_NAME represents the Generative AI provider as identified by the client or server instrumentation. + */ + public static final StringTag GEN_AI_PROVIDER_NAME = new StringTag(26, "gen_ai.provider.name"); + + /** + * GEN_AI_REQUEST_MODEL represents the name of the GenAI model a request is being made to. + */ + public static final StringTag GEN_AI_REQUEST_MODEL = new StringTag(27, "gen_ai.request.model"); + + /** + * GEN_AI_TOP_K represents the top_k sampling setting for the GenAI request. + */ + public static final StringTag GEN_AI_TOP_K = new StringTag(28, "gen_ai.request.top_k"); + + /** + * GEN_AI_TOP_P represents the top_p sampling setting for the GenAI request. + */ + public static final StringTag GEN_AI_TOP_P = new StringTag(29, "gen_ai.request.top_p"); + + /** + * GEN_AI_TEMPERATURE represents the temperature setting for the GenAI request. + */ + public static final StringTag GEN_AI_TEMPERATURE = new StringTag(30, "gen_ai.request.temperature"); + + /** + * GEN_AI_TOOL_NAME represents the name of the tool utilized by the agent. + */ + public static final StringTag GEN_AI_TOOL_NAME = new StringTag(31, "gen_ai.tool.name"); + + /** + * GEN_AI_TOOL_CALL_ARGUMENTS represents the parameters passed to the tool call. + */ + public static final StringTag GEN_AI_TOOL_CALL_ARGUMENTS = new StringTag(32, "gen_ai.tool.call.arguments"); + + /** + * GEN_AI_TOOL_CALL_RESULT represents the result returned by the tool call (if any and if execution was successful). + */ + public static final StringTag GEN_AI_TOOL_CALL_RESULT = new StringTag(33, "gen_ai.tool.call.result"); + + /** + * GEN_AI_RESPONSE_MODEL represents the name of the model that generated the response. + */ + public static final StringTag GEN_AI_RESPONSE_MODEL = new StringTag(34, "gen_ai.response.model"); + + /** + * GEN_AI_RESPONSE_ID represents the unique identifier for the completion. + */ + public static final StringTag GEN_AI_RESPONSE_ID = new StringTag(35, "gen_ai.response.id"); + + /** + * GEN_AI_USAGE_INPUT_TOKENS represents the number of tokens used in the GenAI input (prompt). + */ + public static final StringTag GEN_AI_USAGE_INPUT_TOKENS = new StringTag(36, "gen_ai.usage.input_tokens"); + + /** + * GEN_AI_USAGE_OUTPUT_TOKENS represents the number of tokens used in the GenAI response (completion). + */ + public static final StringTag GEN_AI_USAGE_OUTPUT_TOKENS = new StringTag(37, "gen_ai.usage.output_tokens"); + + /** + * GEN_AI_USAGE_TOTAL_TOKENS represents the total number of tokens used in the GenAI exchange. + */ + public static final StringTag GEN_AI_CLIENT_TOKEN_USAGE = new StringTag(38, "gen_ai.client.token.usage"); + + /** + * GEN_AI_RESPONSE_FINISH_REASONS represents the array of reasons the model stopped generating tokens. + */ + public static final StringTag GEN_AI_RESPONSE_FINISH_REASONS = new StringTag(39, "gen_ai.response.finish_reasons"); + + /** + * GEN_AI_STREAM_TTFR represents the time to first response (TTFR) for streaming operations. + */ + public static final StringTag GEN_AI_STREAM_TTFR = new StringTag(40, "gen_ai.stream.ttfr"); + + /** + * GEN_AI_INPUT_MESSAGES represents the chat history provided to the model as an input. + */ + public static final StringTag GEN_AI_INPUT_MESSAGES = new StringTag(44, "gen_ai.input.messages"); + + /** + * GEN_AI_OUTPUT_MESSAGES represents the messages returned by the model where each message represents a specific model response (choice, candidate). + */ + public static final StringTag GEN_AI_OUTPUT_MESSAGES = new StringTag(45, "gen_ai.output.messages"); + /** * Creates a {@code StringTag} with the given key and cache it, if it's created before, simply return it without * creating a new one. diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/SpanLayer.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/SpanLayer.java index 4ee9395ac9..c31fdc4cc1 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/SpanLayer.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/trace/SpanLayer.java @@ -19,7 +19,8 @@ package org.apache.skywalking.apm.agent.core.context.trace; public enum SpanLayer { - DB(1), RPC_FRAMEWORK(2), HTTP(3), MQ(4), CACHE(5); + DB(1), RPC_FRAMEWORK(2), HTTP(3), MQ(4), CACHE(5), + GEN_AI(7); private int code; @@ -50,4 +51,8 @@ public static void asHttp(AbstractSpan span) { public static void asMQ(AbstractSpan span) { span.setLayer(SpanLayer.MQ); } + + public static void asGenAI(AbstractSpan span) { + span.setLayer(SpanLayer.GEN_AI); + } } diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/GsonUtil.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/GsonUtil.java new file mode 100644 index 0000000000..fb710e4a61 --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/GsonUtil.java @@ -0,0 +1,36 @@ +/* + * 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.agent.core.util; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class GsonUtil { + + private static final Gson GSON = new GsonBuilder() + .disableHtmlEscaping() + .create(); + + public static String toJson(Object src) { + if (src == null) { + return null; + } + return GSON.toJson(src); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml index 609220e725..5a307810b3 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml @@ -45,6 +45,7 @@ spring-webflux-5.x-webclient-plugin spring-webflux-6.x-webclient-plugin resttemplate-commons + spring-ai-1.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml new file mode 100644 index 0000000000..b6ea5c9863 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml @@ -0,0 +1,47 @@ + + + + + + spring-plugins + org.apache.skywalking + 9.7.0-SNAPSHOT + + 4.0.0 + + spring-ai-1.x-plugin + jar + + spring-ai-1.x-plugin + http://maven.apache.org + + + 17 + + + + + org.springframework.ai + spring-ai-client-chat + 1.1.0 + provided + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java new file mode 100644 index 0000000000..302db3c407 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java @@ -0,0 +1,179 @@ +/* + * 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.spring.ai.v1; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.config.SpringAiPluginConfig; +import org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants; +import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.InputMessages; +import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.OutputMessages; +import org.springframework.ai.chat.metadata.ChatResponseMetadata; +import org.springframework.ai.chat.metadata.Usage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.Prompt; + +import java.lang.reflect.Method; + +public class ChatModelCallInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + ChatModelMetadataResolver.ApiMetadata apiMetadata = ChatModelMetadataResolver.getMetadata(objInst); + AbstractSpan span = ContextManager.createExitSpan("Spring-ai/" + apiMetadata.getProviderName() + "/call", apiMetadata.getPeer()); + SpanLayer.asGenAI(span); + span.setComponent(apiMetadata.getComponent()); + Tags.GEN_AI_OPERATION_NAME.set(span, Constants.CHAT); + Tags.GEN_AI_PROVIDER_NAME.set(span, apiMetadata.getProviderName()); + + Prompt prompt = (Prompt) allArguments[0]; + ChatOptions chatOptions = prompt.getOptions(); + if (chatOptions == null) { + return; + } + + if (chatOptions.getModel() != null) { + Tags.GEN_AI_REQUEST_MODEL.set(span, chatOptions.getModel()); + } + if (chatOptions.getTemperature() != null) { + Tags.GEN_AI_TEMPERATURE.set(span, String.valueOf(chatOptions.getTemperature())); + } + if (chatOptions.getTopK() != null) { + Tags.GEN_AI_TOP_K.set(span, String.valueOf(chatOptions.getTopK())); + } + if (chatOptions.getTopP() != null) { + Tags.GEN_AI_TOP_P.set(span, String.valueOf(chatOptions.getTopP())); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + if (!ContextManager.isActive()) { + return ret; + } + + try { + if (!(ret instanceof ChatResponse)) { + return ret; + } + + ChatResponse response = (ChatResponse) ret; + + AbstractSpan span = ContextManager.activeSpan(); + ChatResponseMetadata metadata = response.getMetadata(); + + long totalTokens = 0; + + if (metadata != null) { + if (metadata.getId() != null) { + Tags.GEN_AI_RESPONSE_ID.set(span, metadata.getId()); + } + if (metadata.getModel() != null) { + Tags.GEN_AI_RESPONSE_MODEL.set(span, metadata.getModel()); + } + + Usage usage = metadata.getUsage(); + if (usage != null) { + if (usage.getPromptTokens() != null) { + Tags.GEN_AI_USAGE_INPUT_TOKENS.set(span, String.valueOf(usage.getPromptTokens())); + } + if (usage.getCompletionTokens() != null) { + Tags.GEN_AI_USAGE_OUTPUT_TOKENS.set(span, String.valueOf(usage.getCompletionTokens())); + } + if (usage.getTotalTokens() != null) { + totalTokens = usage.getTotalTokens(); + Tags.GEN_AI_CLIENT_TOKEN_USAGE.set(span, String.valueOf(totalTokens)); + } + } + } + + Generation generation = response.getResult(); + if (generation != null && generation.getMetadata() != null) { + String finishReason = generation.getMetadata().getFinishReason(); + if (finishReason != null) { + Tags.GEN_AI_RESPONSE_FINISH_REASONS.set(span, finishReason); + } + } + + collectContent(span, allArguments, response, totalTokens); + } finally { + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().log(t); + } + } + + private void collectContent(AbstractSpan span, Object[] allArguments, ChatResponse response, long totalTokens) { + int tokenThreshold = SpringAiPluginConfig.Plugin.SpringAi.CONTENT_COLLECT_THRESHOLD_TOKENS; + + if (tokenThreshold >= 0 && totalTokens < tokenThreshold) { + return; + } + + if (SpringAiPluginConfig.Plugin.SpringAi.COLLECT_INPUT_MESSAGES) { + collectPrompt(span, allArguments); + } + + if (SpringAiPluginConfig.Plugin.SpringAi.COLLECT_OUTPUT_MESSAGES) { + collectCompletion(span, response); + } + } + + private void collectPrompt(AbstractSpan span, Object[] allArguments) { + Prompt prompt = (Prompt) allArguments[0]; + if (prompt == null) { + return; + } + + InputMessages inputMessages = InputMessages.fromPrompt(prompt); + String inputMessagesJson = inputMessages.toJson(); + int limit = SpringAiPluginConfig.Plugin.SpringAi.INPUT_MESSAGES_LENGTH_LIMIT; + if (limit > 0 && inputMessagesJson.length() > limit) { + inputMessagesJson = inputMessagesJson.substring(0, limit); + } + + Tags.GEN_AI_INPUT_MESSAGES.set(span, inputMessagesJson); + } + + private void collectCompletion(AbstractSpan span, ChatResponse response) { + + OutputMessages outputMessages = OutputMessages.fromChatResponse(response); + String outputMessagesJson = outputMessages.toJson(); + int limit = SpringAiPluginConfig.Plugin.SpringAi.OUTPUT_MESSAGES_LENGTH_LIMIT; + + if (limit > 0 && outputMessagesJson.length() > limit) { + outputMessagesJson = outputMessagesJson.substring(0, limit); + } + Tags.GEN_AI_OUTPUT_MESSAGES.set(span, outputMessagesJson); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java new file mode 100644 index 0000000000..9abb852187 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java @@ -0,0 +1,266 @@ +/* + * 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.spring.ai.v1; + +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.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.config.SpringAiPluginConfig; +import org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants; +import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.InputMessages; +import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.OutputMessages; +import org.springframework.ai.chat.metadata.ChatResponseMetadata; +import org.springframework.ai.chat.metadata.Usage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; +import org.springframework.ai.chat.prompt.ChatOptions; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.util.StringUtils; +import reactor.core.publisher.Flux; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +public class ChatModelStreamInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + ChatModelMetadataResolver.ApiMetadata apiMetadata = ChatModelMetadataResolver.getMetadata(objInst); + AbstractSpan span = ContextManager.createExitSpan("Spring-ai/" + apiMetadata.getProviderName() + "/stream", apiMetadata.getPeer()); + SpanLayer.asGenAI(span); + + span.setComponent(apiMetadata.getComponent()); + Tags.GEN_AI_OPERATION_NAME.set(span, Constants.CHAT); + Tags.GEN_AI_PROVIDER_NAME.set(span, apiMetadata.getProviderName()); + + Prompt prompt = (Prompt) allArguments[0]; + if (prompt == null) { + return; + } + + ChatOptions chatOptions = prompt.getOptions(); + if (chatOptions == null) { + return; + } + + Tags.GEN_AI_REQUEST_MODEL.set(span, chatOptions.getModel()); + Tags.GEN_AI_TEMPERATURE.set(span, String.valueOf(chatOptions.getTemperature())); + Tags.GEN_AI_TOP_K.set(span, String.valueOf(chatOptions.getTopK())); + Tags.GEN_AI_TOP_P.set(span, String.valueOf(chatOptions.getTopP())); + + ContextManager.getRuntimeContext().put(Constants.SPRING_AI_STREAM_START_TIME, System.currentTimeMillis()); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + if (!ContextManager.isActive()) { + return ret; + } + + final AbstractSpan span = ContextManager.activeSpan(); + final ContextSnapshot snapshot = ContextManager.capture(); + + span.prepareForAsync(); + ContextManager.stopSpan(); + + @SuppressWarnings("unchecked") final Flux flux = (Flux) ret; + + final StreamState state = new StreamState(readAndClearStartTime()); + + return flux + .doOnNext(response -> onStreamNext(span, response, state)) + .doOnError(span::log) + .doFinally(signalType -> onStreamFinally(span, allArguments, state)) + .contextWrite(c -> c.put(Constants.SKYWALKING_CONTEXT_SNAPSHOT, snapshot)); + } + + private void onStreamNext(AbstractSpan span, ChatResponse response, StreamState state) { + state.lastResponseRef.set(response); + + final Generation generation = response.getResult(); + if (generation == null) { + return; + } + + recordTtfrIfFirstToken(span, generation, state); + recordFinishReason(generation, state); + appendCompletionChunk(generation, state); + } + + private void onStreamFinally(AbstractSpan span, Object[] allArguments, StreamState state) { + try { + ChatResponse finalResponse = state.lastResponseRef.get(); + long totalTokens = 0; + + if (finalResponse != null && finalResponse.getMetadata() != null) { + ChatResponseMetadata metadata = finalResponse.getMetadata(); + collectResponseTags(span, metadata, state); + totalTokens = collectUsageTags(span, metadata.getUsage()); + } + + int tokenThreshold = SpringAiPluginConfig.Plugin.SpringAi.CONTENT_COLLECT_THRESHOLD_TOKENS; + if (tokenThreshold >= 0 && totalTokens < tokenThreshold) { + return; + } + + if (SpringAiPluginConfig.Plugin.SpringAi.COLLECT_INPUT_MESSAGES) { + collectPrompt(span, allArguments); + } + + if (SpringAiPluginConfig.Plugin.SpringAi.COLLECT_OUTPUT_MESSAGES) { + collectCompletion(span, state); + } + } catch (Throwable t) { + span.log(t); + } finally { + span.asyncFinish(); + } + } + + private void recordTtfrIfFirstToken(AbstractSpan span, Generation generation, StreamState state) { + if (state.startTime == null) { + return; + } + if (generation.getOutput() == null || !StringUtils.hasText(generation.getOutput().getText())) { + return; + } + if (state.firstResponseReceived.compareAndSet(false, true)) { + Tags.GEN_AI_STREAM_TTFR.set(span, String.valueOf(System.currentTimeMillis() - state.startTime)); + } + } + + private void recordFinishReason(Generation generation, StreamState state) { + if (generation.getMetadata() == null) { + return; + } + String reason = generation.getMetadata().getFinishReason(); + if (reason != null) { + state.finishReason.set(reason); + } + } + + private void appendCompletionChunk(Generation generation, StreamState state) { + if (generation.getOutput() == null) { + return; + } + String text = generation.getOutput().getText(); + if (text != null) { + state.completionBuilder.append(text); + } + } + + private void collectResponseTags(AbstractSpan span, ChatResponseMetadata metadata, StreamState state) { + if (metadata.getId() != null) { + Tags.GEN_AI_RESPONSE_ID.set(span, metadata.getId()); + } + if (metadata.getModel() != null) { + Tags.GEN_AI_RESPONSE_MODEL.set(span, metadata.getModel()); + } + Tags.GEN_AI_RESPONSE_FINISH_REASONS.set(span, state.finishReason.get()); + } + + private long collectUsageTags(AbstractSpan span, Usage usage) { + if (usage == null) { + return 0; + } + + if (usage.getPromptTokens() != null) { + Tags.GEN_AI_USAGE_INPUT_TOKENS.set(span, String.valueOf(usage.getPromptTokens())); + } + + if (usage.getCompletionTokens() != null) { + Tags.GEN_AI_USAGE_OUTPUT_TOKENS.set(span, String.valueOf(usage.getCompletionTokens())); + } + + long total = usage.getTotalTokens() != null ? usage.getTotalTokens() : 0; + Tags.GEN_AI_CLIENT_TOKEN_USAGE.set(span, String.valueOf(total)); + return total; + } + + private void collectPrompt(AbstractSpan span, Object[] allArguments) { + Prompt prompt = (Prompt) allArguments[0]; + if (prompt == null) { + return; + } + + InputMessages inputMessages = InputMessages.fromPrompt(prompt); + String inputMessagesJson = inputMessages.toJson(); + + int limit = SpringAiPluginConfig.Plugin.SpringAi.INPUT_MESSAGES_LENGTH_LIMIT; + if (limit > 0 && inputMessagesJson.length() > limit) { + inputMessagesJson = inputMessagesJson.substring(0, limit); + } + + Tags.GEN_AI_INPUT_MESSAGES.set(span, inputMessagesJson); + } + + private void collectCompletion(AbstractSpan span, StreamState state) { + + String fullText = state.completionBuilder.toString(); + String finishReason = state.finishReason.get(); + List parts = new ArrayList<>(); + if (fullText != null && !fullText.isEmpty()) { + parts.add(new InputMessages.TextPart(fullText)); + } + + OutputMessages outputMessages = OutputMessages.create().append(OutputMessages.OutputMessage.create("assistant", parts, finishReason)); + String outputMessagesJson = outputMessages.toJson(); + + int limit = SpringAiPluginConfig.Plugin.SpringAi.OUTPUT_MESSAGES_LENGTH_LIMIT; + if (limit > 0 && outputMessagesJson.length() > limit) { + outputMessagesJson = outputMessagesJson.substring(0, limit); + } + + Tags.GEN_AI_OUTPUT_MESSAGES.set(span, outputMessagesJson); + } + + private Long readAndClearStartTime() { + Long startTime = (Long) ContextManager.getRuntimeContext().get(Constants.SPRING_AI_STREAM_START_TIME); + ContextManager.getRuntimeContext().remove(Constants.SPRING_AI_STREAM_START_TIME); + return startTime; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().log(t); + } + } + + private static final class StreamState { + final AtomicReference lastResponseRef = new AtomicReference<>(); + final StringBuilder completionBuilder = new StringBuilder(); + final AtomicReference finishReason = new AtomicReference<>(""); + final AtomicBoolean firstResponseReceived = new AtomicBoolean(false); + final Long startTime; + + StreamState(Long startTime) { + this.startTime = startTime; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/DefaultToolCallingManagerInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/DefaultToolCallingManagerInterceptor.java new file mode 100644 index 0000000000..929fd9bbd8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/DefaultToolCallingManagerInterceptor.java @@ -0,0 +1,63 @@ +/* + * 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.spring.ai.v1; + +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 org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants; +import org.springframework.ai.model.tool.internal.ToolCallReactiveContextHolder; +import reactor.util.context.ContextView; + +import java.lang.reflect.Method; + +public class DefaultToolCallingManagerInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + AbstractSpan span = ContextManager.createLocalSpan("Spring-ai/tool/call"); + span.setComponent(ComponentsDefine.SPRING_AI); + + ContextView reactorCtx = ToolCallReactiveContextHolder.getContext(); + + if (reactorCtx != null && reactorCtx.hasKey(Constants.SKYWALKING_CONTEXT_SNAPSHOT)) { + ContextSnapshot snapshot = reactorCtx.get(Constants.SKYWALKING_CONTEXT_SNAPSHOT); + ContextManager.continued(snapshot); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + 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/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ToolCallbackCallInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ToolCallbackCallInterceptor.java new file mode 100644 index 0000000000..637599da57 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ToolCallbackCallInterceptor.java @@ -0,0 +1,79 @@ +/* + * 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.spring.ai.v1; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +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 org.apache.skywalking.apm.plugin.spring.ai.v1.config.SpringAiPluginConfig; +import org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants; +import org.springframework.ai.tool.ToolCallback; +import org.springframework.ai.tool.definition.ToolDefinition; + +import java.lang.reflect.Method; + +public class ToolCallbackCallInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + ToolCallback toolCallback = (ToolCallback) objInst; + ToolDefinition definition = toolCallback.getToolDefinition(); + + String toolName = definition.name(); + + AbstractSpan span = ContextManager.createLocalSpan("Spring-ai/tool/execute/" + toolName); + span.setComponent(ComponentsDefine.SPRING_AI); + + Tags.GEN_AI_TOOL_NAME.set(span, toolName); + Tags.GEN_AI_OPERATION_NAME.set(span, Constants.EXECUTE_TOOL); + + if (SpringAiPluginConfig.Plugin.SpringAi.COLLECT_TOOL_INPUT) { + String toolInput = (String) allArguments[0]; + Tags.GEN_AI_TOOL_CALL_ARGUMENTS.set(span, toolInput); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (ContextManager.isActive()) { + AbstractSpan span = ContextManager.activeSpan(); + if (SpringAiPluginConfig.Plugin.SpringAi.COLLECT_TOOL_OUTPUT && ret != null) { + Tags.GEN_AI_TOOL_CALL_RESULT.set(span, (String) ret); + } + + ContextManager.stopSpan(); + } + + 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/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/ChatModelMetadataResolver.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/ChatModelMetadataResolver.java new file mode 100644 index 0000000000..501f5e026c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/ChatModelMetadataResolver.java @@ -0,0 +1,147 @@ +/* + * 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.spring.ai.v1.common; + +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.apache.skywalking.apm.network.trace.component.OfficialComponent; +import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum; + +import javax.validation.constraints.NotNull; +import java.util.HashMap; +import java.util.Map; + +public class ChatModelMetadataResolver { + + private static final ILog LOGGER = LogManager.getLogger(ChatModelMetadataResolver.class); + + private static final Map MODEL_METADATA_MAP = new HashMap<>(); + + static { + for (AiProviderEnum provider : AiProviderEnum.values()) { + if (provider.getModelClassName() != null && provider.getValue() != null) { + MODEL_METADATA_MAP.put( + provider.getModelClassName(), + new ApiMetadata(provider.getValue(), matchComponent(provider)) + ); + } + } + } + + private static OfficialComponent matchComponent(AiProviderEnum provider) { + switch (provider) { + case ANTHROPIC_CLAUDE: + return ComponentsDefine.SPRING_AI_ANTHROPIC; + case AMAZON_BEDROCK_CONVERSE: + return ComponentsDefine.SPRING_AI_BEDROCK; + case AZURE_OPENAI: + return ComponentsDefine.SPRING_AI_AZURE_OPENAI; + case OCI_GENAI_COHERE: + return ComponentsDefine.SPRING_AI_COHERE; + case DEEPSEEK: + return ComponentsDefine.SPRING_AI_DEEPSEEK; + case GOOGLE_GENAI: + return ComponentsDefine.SPRING_AI_GOOGLE_GENAI; + case GOOGLE_VERTEXAI_GEMINI: + return ComponentsDefine.SPRING_AI_VERTEXAI; + case MISTRAL_AI: + return ComponentsDefine.SPRING_AI_MISTRAL_AI; + case OPENAI: + return ComponentsDefine.SPRING_AI_OPENAI; + case HUGGINGFACE: + return ComponentsDefine.SPRING_AI_HUGGINGFACE; + case MINIMAX: + return ComponentsDefine.SPRING_AI_MINIMAX; + case OLLAMA: + return ComponentsDefine.SPRING_AI_OLLAMA; + case OPENAI_SDK_OFFICIAL: + return ComponentsDefine.SPRING_AI_OPENAI; + case ZHIPU_AI: + return ComponentsDefine.SPRING_AI_ZHIPU_AI; + case UNKNOWN: + default: + return ComponentsDefine.SPRING_AI_UNKNOWN; + } + } + + @NotNull + public static ApiMetadata getMetadata(Object chatModelInstance) { + ApiMetadata metadata = MODEL_METADATA_MAP.get(chatModelInstance.getClass().getName()); + if (metadata == null) { + MODEL_METADATA_MAP.get(AiProviderEnum.UNKNOWN); + } + return metadata; + } + + public static ApiMetadata getMetadata(String modelClassName) { + try { + return MODEL_METADATA_MAP.get(modelClassName); + } catch (Exception e) { + LOGGER.error("spring-ai plugin get modelMetadata error: ", e); + return null; + } + } + + public static class ApiMetadata { + + private final String providerName; + private final OfficialComponent component; + private volatile String baseUrl; + private volatile String completionsPath; + + ApiMetadata(String providerName, OfficialComponent component) { + this.providerName = providerName; + this.component = component; + } + + public String getProviderName() { + return providerName; + } + + public OfficialComponent getComponent() { + return component; + } + + public String getBaseUrl() { + return baseUrl; + } + + public void setBaseUrl(String baseUrl) { + this.baseUrl = baseUrl; + } + + public String getCompletionsPath() { + return completionsPath; + } + + public void setCompletionsPath(String completionsPath) { + this.completionsPath = completionsPath; + } + + public String getPeer() { + if (baseUrl != null && !baseUrl.isEmpty()) { + return completionsPath != null && !completionsPath.isEmpty() + ? baseUrl + completionsPath + : baseUrl; + } + return providerName; + } + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java new file mode 100644 index 0000000000..d2d5eef6f6 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java @@ -0,0 +1,74 @@ +/* + * 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.spring.ai.v1.config; + +import org.apache.skywalking.apm.agent.core.boot.PluginConfig; + +public class SpringAiPluginConfig { + + public static class Plugin { + + @PluginConfig(root = SpringAiPluginConfig.class) + public static class SpringAi { + + /** + * Whether to collect the prompt content (input text) of the GenAI request. + */ + public static boolean COLLECT_INPUT_MESSAGES = false; + + /** + * Whether to collect the completion content (output text) of the GenAI response. + */ + public static boolean COLLECT_OUTPUT_MESSAGES = false; + + /** + * The maximum characters of the collected prompt content. + * If the content exceeds this limit, it will be truncated. + * Use a negative value to represent no limit, but be aware this could cause OOM. + */ + public static int INPUT_MESSAGES_LENGTH_LIMIT = 1024; + + /** + * The maximum characters of the collected completion content. + * If the content exceeds this limit, it will be truncated. + * Use a negative value to represent no limit, but be aware this could cause OOM. + */ + public static int OUTPUT_MESSAGES_LENGTH_LIMIT = 1024; + + /** + * The threshold for token usage to trigger content collection. + * When set to a positive value, prompt and completion will only be collected + * if the total token usage of the request exceeds this threshold. + * * This requires {@link #COLLECT_INPUT_MESSAGES} or {@link #COLLECT_OUTPUT_MESSAGES} to be enabled first. + * Use a negative value to disable this threshold-based filtering (collect all). + */ + public static int CONTENT_COLLECT_THRESHOLD_TOKENS = -1; + + /** + * Whether to collect the arguments (input parameters) of the tool/function call. + */ + public static boolean COLLECT_TOOL_INPUT = false; + + /** + * Whether to collect the execution result (output) of the tool/function call. + */ + public static boolean COLLECT_TOOL_OUTPUT = false; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/contant/Constants.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/contant/Constants.java new file mode 100644 index 0000000000..7348a0c11f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/contant/Constants.java @@ -0,0 +1,31 @@ +/* + * 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.spring.ai.v1.contant; + +public class Constants { + public static final String SPRING_AI_STREAM_START_TIME = "Spring-ai.stream.startTime"; + + public static final String SKYWALKING_CONTEXT_SNAPSHOT = "SKYWALKING_CONTEXT_SNAPSHOT"; + + public static final String CHAT = "chat"; + + public static final String EXECUTE_TOOL = "execute_tool"; + + public static final String DEFAULT_COMPLETIONS_PATH = "/v1/chat/completions"; +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/ChatModelInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/ChatModelInstrumentation.java new file mode 100644 index 0000000000..13aa1d381d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/ChatModelInstrumentation.java @@ -0,0 +1,92 @@ +/* + * 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.spring.ai.v1.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 net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; + +public class ChatModelInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.chat.model.ChatModel"; + + private static final String INTERCEPT_CALL_METHOD = "call"; + + private static final String INTERCEPT_STREAM_METHOD = "stream"; + + private static final String INTERCEPTOR_CALL_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.ChatModelCallInterceptor"; + + private static final String INTERCEPTOR_STREAM_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.ChatModelStreamInterceptor"; + + @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 getMethodsMatcher() { + return named(INTERCEPT_CALL_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CALL_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(INTERCEPT_STREAM_METHOD).and(takesArguments(1)).and(takesArgumentWithType(0, "org.springframework.ai.chat.prompt.Prompt")); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_STREAM_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/DefaultToolCallingManagerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/DefaultToolCallingManagerInstrumentation.java new file mode 100644 index 0000000000..595472834f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/DefaultToolCallingManagerInstrumentation.java @@ -0,0 +1,72 @@ +/* + * 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.spring.ai.v1.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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; + +public class DefaultToolCallingManagerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.model.tool.DefaultToolCallingManager"; + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.DefaultToolCallingManagerInterceptor"; + + private static final String INTERCEPT_METHOD = "executeToolCall"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(INTERCEPT_METHOD).and(takesArguments(3)).and(takesArgumentWithType(0, "org.springframework.ai.chat.prompt.Prompt")); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/ToolCallbackInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/ToolCallbackInstrumentation.java new file mode 100644 index 0000000000..99a4029b00 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/ToolCallbackInstrumentation.java @@ -0,0 +1,73 @@ +/* + * 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.spring.ai.v1.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 net.bytebuddy.matcher.ElementMatchers.returns; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; + +public class ToolCallbackInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_INTERFACE = "org.springframework.ai.tool.ToolCallback"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.ToolCallbackCallInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return HierarchyMatch.byHierarchyMatch(ENHANCE_INTERFACE); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("call") + .and(takesArguments(2)) + .and(takesArgumentWithType(0, "java.lang.String")) + .and(returns(named("java.lang.String"))); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/AnthropicApiInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/AnthropicApiInstrumentation.java new file mode 100644 index 0000000000..e226864906 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/AnthropicApiInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.ai.v1.define.provider; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class AnthropicApiInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.anthropic.api.AnthropicApi"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.provider.AnthropicApiConstructorInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(8).and(takesArgument(0, named("java.lang.String"))).and(takesArgument(1, named("java.lang.String"))); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/DeepSeekApiInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/DeepSeekApiInstrumentation.java new file mode 100644 index 0000000000..17382e75eb --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/DeepSeekApiInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.ai.v1.define.provider; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class DeepSeekApiInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.deepseek.api.DeepSeekApi"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.provider.DeepSeekApiConstructorInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(8).and(takesArgument(0, named("java.lang.String"))).and(takesArgument(3, named("java.lang.String"))); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/HuggingfaceChatModelInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/HuggingfaceChatModelInstrumentation.java new file mode 100644 index 0000000000..93f7b57af4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/HuggingfaceChatModelInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.ai.v1.define.provider; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class HuggingfaceChatModelInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.huggingface.HuggingfaceChatModel"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.provider.HuggingfaceChatModelConstructorInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(2).and(takesArgument(1, named("java.lang.String"))); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/MiniMaxApiInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/MiniMaxApiInstrumentation.java new file mode 100644 index 0000000000..c8a5ca3ad1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/MiniMaxApiInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.ai.v1.define.provider; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class MiniMaxApiInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.minimax.api.MiniMaxApi"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.provider.MiniMaxApiConstructorInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(4).and(takesArgument(0, named("java.lang.String"))); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/MistralAiApiInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/MistralAiApiInstrumentation.java new file mode 100644 index 0000000000..ffcaee9198 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/MistralAiApiInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.ai.v1.define.provider; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class MistralAiApiInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.mistralai.api.MistralAiApi"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.provider.MistralAiApiConstructorInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(5).and(takesArgument(0, named("java.lang.String"))); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/OllamaApiInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/OllamaApiInstrumentation.java new file mode 100644 index 0000000000..7e8fd5ebd8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/OllamaApiInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.ai.v1.define.provider; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class OllamaApiInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.ollama.api.OllamaApi"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.provider.OllamaApiConstructorInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(4).and(takesArgument(0, named("java.lang.String"))); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/OpenAiApiInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/OpenAiApiInstrumentation.java new file mode 100644 index 0000000000..624262322e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/OpenAiApiInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.ai.v1.define.provider; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class OpenAiApiInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.openai.api.OpenAiApi"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.provider.OpenAiApiConstructorInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(8).and(takesArgument(0, named("java.lang.String"))).and(takesArgument(3, named("java.lang.String"))); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/ZhiPuAiApiInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/ZhiPuAiApiInstrumentation.java new file mode 100644 index 0000000000..583f045f6b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/provider/ZhiPuAiApiInstrumentation.java @@ -0,0 +1,64 @@ +/* + * 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.spring.ai.v1.define.provider; + +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.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +public class ZhiPuAiApiInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.zhipuai.api.ZhiPuAiApi"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.ai.v1.provider.ZhiPuAiApiConstructorInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(8).and(takesArgument(0, named("java.lang.String"))).and(takesArgument(3, named("java.lang.String"))); + } + + @Override + public String getConstructorInterceptor() { + return INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/enums/AiProviderEnum.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/enums/AiProviderEnum.java new file mode 100644 index 0000000000..5137ab7d7e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/enums/AiProviderEnum.java @@ -0,0 +1,68 @@ +/* + * 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.spring.ai.v1.enums; + +public enum AiProviderEnum { + + UNKNOWN("unknown", null), + + ANTHROPIC_CLAUDE("anthropic", "org.springframework.ai.anthropic.AnthropicChatModel"), + + AMAZON_BEDROCK_CONVERSE("aws.bedrock", "org.springframework.ai.bedrock.converse.BedrockProxyChatModel"), + + AZURE_OPENAI("azure.openai", "org.springframework.ai.azure.openai.AzureOpenAiChatModel"), + + OCI_GENAI_COHERE("cohere", "org.springframework.ai.oci.cohere.OCICohereChatModel"), + + DEEPSEEK("deepseek", "org.springframework.ai.deepseek.DeepSeekChatModel"), + + GOOGLE_GENAI("gcp.gen_ai", "org.springframework.ai.google.genai.GoogleGenAiChatModel"), + + GOOGLE_VERTEXAI_GEMINI("gcp.vertex_ai", "org.springframework.ai.vertexai.gemini.VertexAiGeminiChatModel"), + + MISTRAL_AI("mistral_ai", "org.springframework.ai.mistralai.MistralAiChatModel"), + + OPENAI("openai", "org.springframework.ai.openai.OpenAiChatModel"), + + HUGGINGFACE("huggingface", "org.springframework.ai.huggingface.HuggingfaceChatModel"), + + MINIMAX("minimax", "org.springframework.ai.minimax.MiniMaxChatModel"), + + OLLAMA("ollama", "org.springframework.ai.ollama.OllamaChatModel"), + + OPENAI_SDK_OFFICIAL("openai", "org.springframework.ai.openaisdk.OpenAiSdkChatModel"), + + ZHIPU_AI("zhipu_ai", "org.springframework.ai.zhipuai.ZhiPuAiChatModel"); + + private final String value; + private final String modelClassName; + + AiProviderEnum(String value, String modelClassName) { + this.value = value; + this.modelClassName = modelClassName; + } + + public String getValue() { + return value; + } + + public String getModelClassName() { + return modelClassName; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/InputMessages.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/InputMessages.java new file mode 100644 index 0000000000..794748bc49 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/InputMessages.java @@ -0,0 +1,271 @@ +/* + * 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.spring.ai.v1.messages; + +import org.apache.skywalking.apm.agent.core.util.GsonUtil; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.messages.Message; +import org.springframework.ai.chat.messages.MessageType; +import org.springframework.ai.chat.messages.ToolResponseMessage; +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.content.Media; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class InputMessages { + + private final List messages = new ArrayList<>(); + + public static InputMessages create() { + return new InputMessages(); + } + + public InputMessages append(InputMessage message) { + this.messages.add(message); + return this; + } + + public String toJson() { + return GsonUtil.toJson( + messages.stream() + .map(InputMessage::toMap) + .collect(Collectors.toList()) + ); + } + + public static class InputMessage { + private final String role; + private final List parts; + + private InputMessage(String role, List parts) { + this.role = role; + this.parts = parts; + } + + public static InputMessage create(String role, List parts) { + return new InputMessage(role, parts); + } + + public Map toMap() { + List> partMaps = parts.stream() + .map(MessagePart::toMap) + .collect(Collectors.toList()); + + Map map = new HashMap<>(); + map.put("role", role != null ? role : "unknown"); + map.put("parts", partMaps); + return map; + } + } + + public interface MessagePart { + Map toMap(); + } + + public static class TextPart implements MessagePart { + private final String content; + + public TextPart(String content) { + this.content = content; + } + + @Override + public Map toMap() { + return Map.of("type", "text", "content", content != null ? content : ""); + } + } + + public static class ToolCallPart implements MessagePart { + private final String id; + private final String name; + private final String arguments; + + public ToolCallPart(String id, String name, String arguments) { + this.id = id; + this.name = name; + this.arguments = arguments; + } + + @Override + public Map toMap() { + Map map = new java.util.LinkedHashMap<>(); + map.put("type", "tool_call"); + if (id != null) { + map.put("id", id); + } + map.put("name", name != null ? name : ""); + map.put("arguments", arguments != null ? arguments : ""); + return map; + } + } + + public static class ToolCallResponsePart implements MessagePart { + private final String id; + private final String result; + + public ToolCallResponsePart(String id, String result) { + this.id = id; + this.result = result; + } + + @Override + public Map toMap() { + Map map = new LinkedHashMap<>(); + map.put("type", "tool_call_response"); + if (id != null) { + map.put("id", id); + } + map.put("result", result != null ? result : ""); + return map; + } + } + + public static InputMessages fromPrompt(Prompt prompt) { + InputMessages inputMessages = InputMessages.create(); + + if (prompt == null || prompt.getInstructions() == null) { + return inputMessages; + } + + for (Message message : prompt.getInstructions()) { + MessageType type = message.getMessageType(); + + switch (type) { + case SYSTEM: + inputMessages.append(InputMessage.create( + type.getValue(), + textParts(message.getText()) + )); + break; + + case USER: + inputMessages.append(InputMessage.create( + type.getValue(), + userMessageParts(message) + )); + break; + + case ASSISTANT: + inputMessages.append(InputMessage.create( + type.getValue(), + assistantMessageParts(message) + )); + break; + + case TOOL: + inputMessages.append(InputMessage.create( + type.getValue(), + toolMessageParts(message) + )); + break; + default: + inputMessages.append(InputMessage.create( + type.getValue(), + textParts(message.getText()) + )); + break; + } + } + + return inputMessages; + } + + private static List textParts(String text) { + List parts = new ArrayList<>(); + if (text != null && !text.isEmpty()) { + parts.add(new TextPart(text)); + } + return parts; + } + + private static List userMessageParts(Message message) { + List parts = new ArrayList<>(); + + String text = message.getText(); + if (text != null && !text.isEmpty()) { + parts.add(new TextPart(text)); + } + + if (message instanceof UserMessage) { + UserMessage userMessage = (UserMessage) message; + if (userMessage.getMedia() != null) { + for (Media media : userMessage.getMedia()) { + parts.add(new TextPart("[media: " + media.getMimeType() + "]")); + } + } + } + + return parts; + } + + private static List assistantMessageParts(Message message) { + List parts = new ArrayList<>(); + + String text = message.getText(); + if (text != null && !text.isEmpty()) { + parts.add(new TextPart(text)); + } + + if (message instanceof AssistantMessage) { + AssistantMessage assistantMessage = (AssistantMessage) message; + List toolCalls = assistantMessage.getToolCalls(); + if (toolCalls != null) { + for (AssistantMessage.ToolCall toolCall : toolCalls) { + parts.add(new ToolCallPart( + toolCall.id(), + toolCall.name(), + toolCall.arguments() + )); + } + } + } + + return parts; + } + + private static List toolMessageParts(Message message) { + List parts = new ArrayList<>(); + + if (message instanceof ToolResponseMessage) { + ToolResponseMessage toolResponse = (ToolResponseMessage) message; + List responses = toolResponse.getResponses(); + if (responses != null) { + for (ToolResponseMessage.ToolResponse response : responses) { + parts.add(new ToolCallResponsePart( + response.id(), + response.responseData() + )); + } + } + } else { + String text = message.getText(); + if (text != null && !text.isEmpty()) { + parts.add(new ToolCallResponsePart(null, text)); + } + } + + return parts; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/OutputMessages.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/OutputMessages.java new file mode 100644 index 0000000000..bc73165fc0 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/OutputMessages.java @@ -0,0 +1,121 @@ +/* + * 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.spring.ai.v1.messages; + +import org.apache.skywalking.apm.agent.core.util.GsonUtil; +import org.springframework.ai.chat.messages.AssistantMessage; +import org.springframework.ai.chat.model.ChatResponse; +import org.springframework.ai.chat.model.Generation; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class OutputMessages { + private final List messages = new ArrayList<>(); + + public static OutputMessages create() { + return new OutputMessages(); + } + + public OutputMessages append(OutputMessage message) { + this.messages.add(message); + return this; + } + + public String toJson() { + return GsonUtil.toJson( + messages.stream() + .map(OutputMessage::toMap) + .collect(Collectors.toList()) + ); + } + + public static class OutputMessage { + private final String role; + private final List parts; + private final String finishReason; + + private OutputMessage(String role, List parts, String finishReason) { + this.role = role; + this.parts = parts; + this.finishReason = finishReason; + } + + public static OutputMessage create(String role, List parts, String finishReason) { + return new OutputMessage(role, parts, finishReason); + } + + public Map toMap() { + Map map = new LinkedHashMap<>(); + map.put("role", role != null ? role : "assistant"); + map.put("parts", parts.stream() + .map(InputMessages.MessagePart::toMap) + .collect(Collectors.toList())); + if (finishReason != null && !finishReason.isEmpty()) { + map.put("finish_reason", finishReason); + } + return map; + } + } + + public static OutputMessages fromChatResponse(ChatResponse chatResponse) { + OutputMessages outputMessages = OutputMessages.create(); + + if (chatResponse == null || chatResponse.getResults() == null) { + return outputMessages; + } + + for (Generation generation : chatResponse.getResults()) { + List messageParts = new ArrayList<>(); + + AssistantMessage assistantMessage = generation.getOutput(); + if (assistantMessage != null) { + // Text content + String text = assistantMessage.getText(); + if (text != null && !text.isEmpty()) { + messageParts.add(new InputMessages.TextPart(text)); + } + + // Tool calls + List toolCalls = assistantMessage.getToolCalls(); + if (toolCalls != null) { + for (AssistantMessage.ToolCall toolCall : toolCalls) { + messageParts.add(new InputMessages.ToolCallPart( + toolCall.id(), + toolCall.name(), + toolCall.arguments() + )); + } + } + } + + String finishReason = ""; + if (generation.getMetadata() != null && generation.getMetadata().getFinishReason() != null) { + finishReason = generation.getMetadata().getFinishReason().toLowerCase(); + } + + outputMessages.append(OutputMessage.create("assistant", messageParts, finishReason)); + } + + return outputMessages; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/AnthropicApiConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/AnthropicApiConstructorInterceptor.java new file mode 100644 index 0000000000..4f9e73ca7e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/AnthropicApiConstructorInterceptor.java @@ -0,0 +1,38 @@ +/* + * 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.spring.ai.v1.provider; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum; + +public class AnthropicApiConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + ChatModelMetadataResolver.ApiMetadata metadata = ChatModelMetadataResolver.getMetadata(AiProviderEnum.ANTHROPIC_CLAUDE.getModelClassName()); + if (metadata == null) { + return; + } + + metadata.setBaseUrl((String) allArguments[0]); + metadata.setCompletionsPath((String) allArguments[1]); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/DeepSeekApiConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/DeepSeekApiConstructorInterceptor.java new file mode 100644 index 0000000000..e1f26e5e8b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/DeepSeekApiConstructorInterceptor.java @@ -0,0 +1,38 @@ +/* + * 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.spring.ai.v1.provider; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum; + +public class DeepSeekApiConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + ChatModelMetadataResolver.ApiMetadata metadata = ChatModelMetadataResolver.getMetadata(AiProviderEnum.DEEPSEEK.getModelClassName()); + if (metadata == null) { + return; + } + + metadata.setBaseUrl((String) allArguments[0]); + metadata.setCompletionsPath((String) allArguments[3]); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/HuggingfaceChatModelConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/HuggingfaceChatModelConstructorInterceptor.java new file mode 100644 index 0000000000..234b876434 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/HuggingfaceChatModelConstructorInterceptor.java @@ -0,0 +1,37 @@ +/* + * 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.spring.ai.v1.provider; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum; + +public class HuggingfaceChatModelConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + ChatModelMetadataResolver.ApiMetadata metadata = ChatModelMetadataResolver.getMetadata(AiProviderEnum.HUGGINGFACE.getModelClassName()); + if (metadata == null) { + return; + } + + metadata.setBaseUrl((String) allArguments[1]); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/MiniMaxApiConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/MiniMaxApiConstructorInterceptor.java new file mode 100644 index 0000000000..939e440ae1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/MiniMaxApiConstructorInterceptor.java @@ -0,0 +1,38 @@ +/* + * 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.spring.ai.v1.provider; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum; + +public class MiniMaxApiConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + ChatModelMetadataResolver.ApiMetadata metadata = ChatModelMetadataResolver.getMetadata(AiProviderEnum.MINIMAX.getModelClassName()); + if (metadata == null) { + return; + } + + metadata.setBaseUrl((String) allArguments[0]); + metadata.setCompletionsPath("/v1/text/chatcompletion_v2"); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/MistralAiApiConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/MistralAiApiConstructorInterceptor.java new file mode 100644 index 0000000000..07eac44d5b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/MistralAiApiConstructorInterceptor.java @@ -0,0 +1,40 @@ +/* + * 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.spring.ai.v1.provider; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum; + +import static org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants.DEFAULT_COMPLETIONS_PATH; + +public class MistralAiApiConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + ChatModelMetadataResolver.ApiMetadata metadata = ChatModelMetadataResolver.getMetadata(AiProviderEnum.MISTRAL_AI.getModelClassName()); + if (metadata == null) { + return; + } + + metadata.setBaseUrl((String) allArguments[0]); + metadata.setCompletionsPath(DEFAULT_COMPLETIONS_PATH); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/OllamaApiConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/OllamaApiConstructorInterceptor.java new file mode 100644 index 0000000000..abdc2d9f5a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/OllamaApiConstructorInterceptor.java @@ -0,0 +1,38 @@ +/* + * 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.spring.ai.v1.provider; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum; + +public class OllamaApiConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + ChatModelMetadataResolver.ApiMetadata metadata = ChatModelMetadataResolver.getMetadata(AiProviderEnum.OLLAMA.getModelClassName()); + if (metadata == null) { + return; + } + + metadata.setBaseUrl((String) allArguments[0]); + metadata.setCompletionsPath("/api/chat"); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/OpenAiApiConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/OpenAiApiConstructorInterceptor.java new file mode 100644 index 0000000000..da0f3bbf2f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/OpenAiApiConstructorInterceptor.java @@ -0,0 +1,38 @@ +/* + * 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.spring.ai.v1.provider; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum; + +public class OpenAiApiConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + ChatModelMetadataResolver.ApiMetadata metadata = ChatModelMetadataResolver.getMetadata(AiProviderEnum.OPENAI.getModelClassName()); + if (metadata == null) { + return; + } + + metadata.setBaseUrl((String) allArguments[0]); + metadata.setCompletionsPath((String) allArguments[3]); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/ZhiPuAiApiConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/ZhiPuAiApiConstructorInterceptor.java new file mode 100644 index 0000000000..734c807a6a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/provider/ZhiPuAiApiConstructorInterceptor.java @@ -0,0 +1,38 @@ +/* + * 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.spring.ai.v1.provider; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.enums.AiProviderEnum; + +public class ZhiPuAiApiConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable { + ChatModelMetadataResolver.ApiMetadata metadata = ChatModelMetadataResolver.getMetadata(AiProviderEnum.ZHIPU_AI.getModelClassName()); + if (metadata == null) { + return; + } + + metadata.setBaseUrl((String) allArguments[0]); + metadata.setCompletionsPath((String) allArguments[3]); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..5c7eec110c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,27 @@ +# 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. + +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.ChatModelInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.ToolCallbackInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.DefaultToolCallingManagerInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.AnthropicApiInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.DeepSeekApiInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.HuggingfaceChatModelInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.MiniMaxApiInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.MistralAiApiInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.OllamaApiInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.OpenAiApiInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.ZhiPuAiApiInstrumentation diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index 9056993626..84b5c41622 100755 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -339,3 +339,25 @@ plugin.solon.http_body_length_threshold=${SW_PLUGIN_SOLON_HTTP_BODY_LENGTH_THRES plugin.caffeine.operation_mapping_write=${SW_PLUGIN_CAFFEINE_OPERATION_MAPPING_WRITE:put,putAll,remove,clear} # Specify which command should be converted to read operation plugin.caffeine.operation_mapping_read=${SW_PLUGIN_CAFFEINE_OPERATION_MAPPING_READ:getIfPresent,getAllPresent,computeIfAbsent} +# Whether to collect the input messages of the GenAI request. +plugin.springai.collect_input_messages=${SW_PLUGIN_SPRINGAI_COLLECT_INPUT_MESSAGES:false} +# Whether to collect the output messages of the GenAI response. +plugin.springai.collect_output_messages=${SW_PLUGIN_SPRINGAI_COLLECT_OUTPUT_MESSAGES:false} +# The maximum characters of the collected prompt content. +# If the content exceeds this limit, it will be truncated. +# Use a negative value to represent no limit, but be aware this could cause OOM. +plugin.springai.prompt_length_limit=${SW_PLUGIN_SPRINGAI_PROMPT_LENGTH_LIMIT:1024} +# The maximum characters of the collected completion content. +# If the content exceeds this limit, it will be truncated. +# Use a negative value to represent no limit, but be aware this could cause OOM. +plugin.springai.completion_length_limit=${SW_PLUGIN_SPRINGAI_COMPLETION_LENGTH_LIMIT:1024} +# The threshold for token usage to trigger content collection. +# When set to a positive value, prompt and completion will only be collected +# if the total token usage of the request exceeds this threshold. +# This requires collect_prompt or collect_completion to be enabled first. +# Use a negative value to disable this threshold-based filtering (collect all). +plugin.springai.content_collect_threshold_tokens=${SW_PLUGIN_SPRINGAI_CONTENT_COLLECT_THRESHOLD_TOKENS:-1} +# Whether to collect the arguments (input parameters) of the tool/function call. +plugin.springai.collect_tool_input=${SW_PLUGIN_SPRINGAI_COLLECT_TOOL_INPUT:false} +# Whether to collect the execution result (output) of the tool/function call. +plugin.springai.collect_tool_output=${SW_PLUGIN_SPRINGAI_COLLECT_TOOL_OUTPUT:false} \ 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 c5a5bfd48f..49d1cb9c8e 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -103,6 +103,7 @@ - sharding-sphere-5.0.0 - sofarpc - solrj-7.x +- spring-ai-1.x - spring-annotation - spring-async-annotation-5.x - spring-cloud-feign-1.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index bb841000a4..cdadd27422 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -160,6 +160,8 @@ metrics based on the tracing data. * [MyBatis](https://github.com/mybatis/mybatis-3) 3.4.x -> 3.5.x * Event * [GuavaEventBus](https://github.com/google/guava) 19.x -> 31.x-jre +* GenAI + * [spring-ai](https://github.com/spring-projects/spring-ai) 1.x (OpenAI, Azure OpenAI, Anthropic, Amazon Bedrock, Google GenAI, Google VertexAI, DeepSeek, Mistral AI, ZhiPu AI, MiniMax, Ollama, Cohere, HuggingFace) # Meter Plugins The meter plugin provides the advanced metrics collections, which are not a part of tracing. diff --git a/pom.xml b/pom.xml index 8260a17784..b675688a4a 100755 --- a/pom.xml +++ b/pom.xml @@ -119,7 +119,7 @@ 2.22.0 3.2.0 3.1.0 - 3.2.4 + 3.3.0 3.0.0-M2 3.10.1 3.1.0 diff --git a/test/plugin/agent-test-tools/pom.xml b/test/plugin/agent-test-tools/pom.xml index 374263e7f4..13a08a39da 100644 --- a/test/plugin/agent-test-tools/pom.xml +++ b/test/plugin/agent-test-tools/pom.xml @@ -35,7 +35,7 @@ pom - cf62c1b733fe2861229201a67b9cc0075ac3e236 + 7220c715d280cf0d7421f17bbc8c8de57249914d ${project.basedir}/target/agent-test-tools https://github.com/apache/skywalking-agent-test-tool.git diff --git a/test/plugin/scenarios/rocketmq-5-grpc-scenario/support-version.list b/test/plugin/scenarios/rocketmq-5-grpc-scenario/support-version.list index da0221c8c1..c7b3c10e09 100644 --- a/test/plugin/scenarios/rocketmq-5-grpc-scenario/support-version.list +++ b/test/plugin/scenarios/rocketmq-5-grpc-scenario/support-version.list @@ -16,4 +16,4 @@ # lists your version here (Contains only the last version number of each minor version.) -5.1.4 +5.4.0 diff --git a/test/plugin/scenarios/rocketmq-scenario/support-version.list b/test/plugin/scenarios/rocketmq-scenario/support-version.list index 7de5cb6f6d..8dc0b9e562 100644 --- a/test/plugin/scenarios/rocketmq-scenario/support-version.list +++ b/test/plugin/scenarios/rocketmq-scenario/support-version.list @@ -16,11 +16,11 @@ # lists your version here (Contains only the last version number of each minor version.) -5.1.4 +5.4.0 4.9.4 4.8.0 4.7.1 4.6.0 4.5.2 4.4.0 -4.3.1 +4.3.1 \ No newline at end of file diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/bin/startup.sh b/test/plugin/scenarios/spring-ai-1.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..8cb423ece2 --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-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 -Dskywalking.plugin.springai.collect_input_messages=true -Dskywalking.plugin.springai.collect_output_messages=true -Dskywalking.plugin.springai.collect_tool_input=true -Dskywalking.plugin.springai.collect_tool_output=true -jar ${agent_opts} ${home}/../libs/spring-ai-1.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..161eb6e2f2 --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml @@ -0,0 +1,156 @@ +# 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: spring-ai-1.x-scenario + segmentSize: gt 0 + segments: + - segmentId: not null + spans: + - operationName: Spring-ai/tool/execute/get_weather + parentSpanId: 0 + spanId: 1 + spanLayer: Unknown + startTime: not null + endTime: not null + componentId: 178 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - { key: gen_ai.tool.name, value: get_weather } + - { key: gen_ai.operation.name, value: execute_tool } + - { key: gen_ai.tool.call.arguments, value: '{"arg0":"new york"}' } + - { key: gen_ai.tool.call.result, value: '"Sunny, 10°C"' } + + - operationName: Spring-ai/tool/call + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: not null + endTime: not null + componentId: 178 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + refs: + - { parentEndpoint: 'GET:/spring-ai-1.x-scenario/case/spring-ai-1.x-scenario-case', + networkAddress: '', refType: CrossThread, parentSpanId: 4, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: spring-ai-1.x-scenario, + traceId: not null } + + - segmentId: not null + spans: + - operationName: Spring-ai/tool/execute/get_weather + parentSpanId: 2 + spanId: 3 + spanLayer: Unknown + spanType: Local + startTime: not null + endTime: not null + tags: + - { key: gen_ai.tool.name, value: get_weather } + - { key: gen_ai.operation.name, value: execute_tool } + - { key: gen_ai.tool.call.arguments, value: '{"arg0":"new york"}' } + - { key: gen_ai.tool.call.result, value: '"Sunny, 10°C"' } + + - operationName: Spring-ai/tool/call + parentSpanId: 1 + spanId: 2 + spanLayer: Unknown + startTime: not null + endTime: not null + spanType: Local + + - operationName: Spring-ai/openai/call + parentSpanId: 0 + spanId: 1 + spanLayer: GenAI + startTime: not null + endTime: not null + componentId: 173 + spanType: Exit + peer: http://localhost:8080/spring-ai-1.x-scenario/llm/v1/chat/completions + tags: + - { key: gen_ai.operation.name, value: chat } + - { key: gen_ai.provider.name, value: openai } + - { key: gen_ai.request.model, value: gpt-4.1-2025-04-14 } + - { key: gen_ai.request.temperature, value: '0.7' } + - { key: gen_ai.request.top_p, value: '0.9' } + - { key: gen_ai.response.id, value: 'chatcmpl-CyJXJt7gxwDgz' } + - { key: gen_ai.response.model, value: gpt-4.1-2025-04-14 } + - { key: gen_ai.usage.input_tokens, value: '52' } + - { key: gen_ai.usage.output_tokens, value: '17' } + - { key: gen_ai.client.token.usage, value: '69' } + - { key: gen_ai.response.finish_reasons, value: STOP } + - { key: gen_ai.input.messages, value: not null } + - { key: gen_ai.output.messages, value: not null } + + - operationName: Spring-ai/openai/stream + parentSpanId: 0 + spanId: 4 + spanLayer: GenAI + startTime: not null + endTime: not null + componentId: 173 + spanType: Exit + peer: http://localhost:8080/spring-ai-1.x-scenario/llm/v1/chat/completions + tags: + - { key: gen_ai.operation.name, value: chat } + - { key: gen_ai.provider.name, value: openai } + - { key: gen_ai.request.model, value: gpt-4.1-2025-04-14 } + - { key: gen_ai.request.temperature, value: '0.7' } + - { key: gen_ai.request.top_k, value: null } + - { key: gen_ai.request.top_p, value: '0.9' } + - { key: gen_ai.stream.ttfr, value: not null } + - { key: gen_ai.response.id, value: 'chatcmpl-fc1b64d3' } + - { key: gen_ai.response.model, value: gpt-4.1-2025-04-14 } + - { key: gen_ai.response.finish_reasons, value: STOP } + - { key: gen_ai.usage.input_tokens, value: '104' } + - { key: gen_ai.usage.output_tokens, value: '34' } + - { key: gen_ai.client.token.usage, value: '138' } + - { key: gen_ai.input.messages, value: not null } + - { key: gen_ai.output.messages, value: not null } + + - operationName: /spring-ai-1.x-scenario/llm/v1/chat/completions + parentSpanId: 0 + spanId: 5 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 99 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - { key: url, value: 'http://localhost:8080/spring-ai-1.x-scenario/llm/v1/chat/completions' } + - { key: http.method, value: POST } + - { key: http.status_code, value: '200' } + + - operationName: GET:/spring-ai-1.x-scenario/case/spring-ai-1.x-scenario-case + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + spanType: Entry + componentId: 1 + tags: + - { key: url, value: http://localhost:8080/spring-ai-1.x-scenario/case/spring-ai-1.x-scenario-case } + - { key: http.method, value: GET } + - { key: http.status_code, value: '200' } \ No newline at end of file diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/configuration.yml b/test/plugin/scenarios/spring-ai-1.x-scenario/configuration.yml new file mode 100644 index 0000000000..073d9271d5 --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/configuration.yml @@ -0,0 +1,21 @@ +# 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/spring-ai-1.x-scenario/case/spring-ai-1.x-scenario-case +healthCheck: http://localhost:8080/spring-ai-1.x-scenario/case/healthCheck +startScript: ./bin/startup.sh + diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/pom.xml b/test/plugin/scenarios/spring-ai-1.x-scenario/pom.xml new file mode 100644 index 0000000000..b9d39f538a --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/pom.xml @@ -0,0 +1,156 @@ + + + + 4.0.0 + + org.apache.skywalking + spring-ai-1.x-scenario + 5.0.0 + + + UTF-8 + 17 + 3.8.1 + + + spring-ai-1.x-scenario + + + + org.springframework.boot + spring-boot-starter-web + 3.5.7 + + + + com.alibaba + fastjson + 1.2.83 + + + + org.springframework.ai + spring-ai-client-chat + + + + org.springframework.ai + spring-ai-starter-model-openai + + + + org.projectlombok + lombok + 1.18.42 + + + + + + + + org.springframework.ai + spring-ai-bom + 1.1.0 + pom + import + + + + + + spring-ai-1.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + 3.5.7 + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + false + + + + + org.apache.maven.plugins + maven-jar-plugin + + + empty-javadoc-jar + package + + jar + + + javadoc + ${basedir}/javadoc + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..deed40fcfe --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ./target/spring-ai-1.x-scenario.jar + ./libs + 0775 + + + \ No newline at end of file diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/Application.java b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/Application.java new file mode 100644 index 0000000000..5147a224ee --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/Application.java @@ -0,0 +1,30 @@ +/* + * 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.httpclient; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/config/ChatClientConfig.java b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/config/ChatClientConfig.java new file mode 100644 index 0000000000..79fde137ab --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/config/ChatClientConfig.java @@ -0,0 +1,32 @@ +/* + * 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.httpclient.config; + +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.openai.OpenAiChatModel; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ChatClientConfig { + + @Bean + public ChatClient openAIChatClient(OpenAiChatModel model) { + return ChatClient.create(model); + } +} diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java new file mode 100644 index 0000000000..d6512b726e --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java @@ -0,0 +1,68 @@ +/* + * 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.httpclient.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import test.apache.skywalking.apm.testcase.jdk.httpclient.tool.WeatherTool; + +@RestController +@RequestMapping("/case") +@RequiredArgsConstructor +public class CaseController { + + private final WeatherTool weatherTool; + private final ChatClient chatClient; + + @GetMapping("/healthCheck") + public String healthCheck() { + return "Success"; + } + + @GetMapping("/spring-ai-1.x-scenario-case") + public String testCase() throws Exception { + + String systemPrompt = """ + You are a professional technical assistant. + Strictly use the provided context to answer questions. + If the information is not in the context, say: "I'm sorry, I don't have that information in my knowledge base." + Do not use outside knowledge. Be concise. + """; + + chatClient + .prompt("What's the weather in New York?") + .system(systemPrompt) + .tools(weatherTool) + .call() + .content(); + + chatClient + .prompt("What's the weather in New York?") + .system(systemPrompt) + .tools(weatherTool) + .stream() + .content() + .doOnNext(System.out::println) + .blockLast(); + + return "success"; + } +} diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/LLMMockController.java b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/LLMMockController.java new file mode 100644 index 0000000000..5221245280 --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/LLMMockController.java @@ -0,0 +1,230 @@ +/* + * 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.httpclient.controller; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.io.PrintWriter; +import java.time.Instant; + +@RestController +@RequestMapping("/llm") +public class LLMMockController { + @RequestMapping("/v1/chat/completions") + public Object completions(@RequestBody JSONObject request, HttpServletResponse response) throws IOException { + Boolean isStream = request.getBoolean("stream"); + if (isStream == null) isStream = false; + + JSONArray messages = request.getJSONArray("messages"); + JSONObject lastMessage = messages.getJSONObject(messages.size() - 1); + String lastRole = lastMessage.getString("role"); + + if (isStream) { + response.setContentType("text/event-stream"); + response.setCharacterEncoding("UTF-8"); + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Connection", "keep-alive"); + + PrintWriter writer = response.getWriter(); + String id = "chatcmpl-fc1b64d3"; + long created = Instant.now().getEpochSecond(); + String model = "gpt-4.1-2025-04-14"; + + try { + if ("tool".equals(lastRole)) { + String fullContent = "The weather in New York is currently sunny with a temperature of 10°C."; + writeStreamChunk(writer, id, created, model, "{\"role\":\"assistant\"}", "null"); + + int len = fullContent.length(); + String[] parts = {fullContent.substring(0, len / 3), fullContent.substring(len / 3, len * 2 / 3), fullContent.substring(len * 2 / 3)}; + + for (String part : parts) { + Thread.sleep(50); + writeStreamChunk(writer, id, created, model, "{\"content\":\"" + escapeJson(part) + "\"}", "null"); + } + + writeStreamChunk(writer, id, created, model, "{}", "\"stop\""); + } else { + writeStreamChunk(writer, id, created, model, "{\"role\":\"assistant\"}", "null"); + + String toolCallDelta = """ + { + "tool_calls": [ + { + "index": 0, + "id": "call_iV4bvFIZujbb", + "type": "function", + "function": { + "name": "get_weather", + "arguments": "" + } + } + ] + } + """; + writeStreamChunk(writer, id, created, model, toolCallDelta, "null"); + + String args = "{\\\"arg0\\\":\\\"new york\\\"}"; + String argsDelta = """ + { + "tool_calls": [ + { + "index": 0, + "function": { + "arguments": "%s" + } + } + ] + } + """.formatted(args); + Thread.sleep(50); + writeStreamChunk(writer, id, created, model, argsDelta, "null"); + + writeStreamChunk(writer, id, created, model, "{}", "\"tool_calls\""); + } + + writer.write("data: [DONE]\n\n"); + writer.flush(); + + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + return null; + } + + String toolCallResponse = """ + { + "choices": [ + { + "finish_reason": "tool_calls", + "index": 0, + "message": { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "function": { + "arguments": "{\\"arg0\\":\\"new york\\"}", + "name": "get_weather" + }, + "id": "call_iV4bvFIZujbb", + "type": "function" + } + ] + } + } + ], + "created": 1768490813, + "id": "chatcmpl-CyJXJt7gxwDgz", + "usage": { + "completion_tokens": 17, + "completion_tokens_details": { + "accepted_prediction_tokens": 0, + "audio_tokens": 0, + "reasoning_tokens": 0, + "rejected_prediction_tokens": 0 + }, + "prompt_tokens": 52, + "prompt_tokens_details": { + "audio_tokens": 0, + "cached_tokens": 0 + }, + "total_tokens": 69 + }, + "model": "gpt-4.1-2025-04-14", + "object": "chat.completion" + } + """; + + String finalResponse = """ + { + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "message": { + "content": "The weather in New York is currently sunny with a temperature of 10°C.", + "role": "assistant" + } + } + ], + "created": 1768491057, + "id":"chatcmpl-CyJXJt7gxwDgz", + "model": "gpt-4.1-2025-04-14", + "object": "chat.completion" + } + """; + + if ("tool".equals(lastRole)) { + return JSON.parseObject(finalResponse); + } + + return JSON.parseObject(toolCallResponse); + } + + private void writeStreamChunk(PrintWriter writer, String id, long created, String model, String delta, String finishReason) { + String json = """ + { + "choices": [ + { + "delta": %s, + "finish_reason": %s, + "index": 0, + "logprobs": null + } + ], + "object": "chat.completion.chunk", + "usage": { + "completion_tokens": 17, + "completion_tokens_details": { + "accepted_prediction_tokens": 0, + "audio_tokens": 0, + "reasoning_tokens": 0, + "rejected_prediction_tokens": 0 + }, + "prompt_tokens": 52, + "prompt_tokens_details": { + "audio_tokens": 0, + "cached_tokens": 0 + }, + "total_tokens": 69 + }, + "created": %d, + "system_fingerprint": null, + "model": "%s", + "id": "%s" + } + """.formatted(delta, finishReason, created, model, id); + + String cleanJson = json.replace("\n", "").replace("\r", ""); + writer.write("data: " + cleanJson + "\n\n"); + writer.flush(); + } + + private String escapeJson(String input) { + if (input == null) return ""; + return input.replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r"); + } +} diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/tool/WeatherTool.java b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/tool/WeatherTool.java new file mode 100644 index 0000000000..1606b67436 --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/tool/WeatherTool.java @@ -0,0 +1,33 @@ +/* + * 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.httpclient.tool; + +import org.springframework.ai.tool.annotation.Tool; +import org.springframework.stereotype.Component; + +@Component +public class WeatherTool { + @Tool(name = "get_weather", description = "Get weather by city name") + public String getWeather(String city) { + return switch (city.toLowerCase()) { + case "new york" -> "Sunny, 10°C"; + case "london" -> "Cloudy, 12°C"; + default -> "Unknown city"; + }; + } +} diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..c4f5c58851 --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,35 @@ +# 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 + servlet: + context-path: /spring-ai-1.x-scenario + +spring: + ai: + openai: + api-key: xxxxxxxxxxxxxxxxxxxxxxxxxxx + base-url: http://localhost:8080/spring-ai-1.x-scenario/llm + chat: + options: + model: gpt-4.1-2025-04-14 + temperature: 0.7 + max-tokens: 1000 + top-p: 0.9 + + + diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/support-version.list b/test/plugin/scenarios/spring-ai-1.x-scenario/support-version.list new file mode 100644 index 0000000000..9d9826957c --- /dev/null +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/support-version.list @@ -0,0 +1,18 @@ +# 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. + +1.0.1 +1.1.1 \ No newline at end of file From eb4eb48b245bb7a10403dc04bfe67e6f787da171 Mon Sep 17 00:00:00 2001 From: omerTT <98276573+omertt27@users.noreply.github.com> Date: Thu, 12 Mar 2026 03:01:51 +0300 Subject: [PATCH 096/114] Fix httpclient-5.x plugin injecting sw8 headers into ClickHouse HTTP requests (#797) ClickHouse HTTP interface (port 8123) rejects unknown headers, causing HTTP 400 errors when SkyWalking Java agent injects sw8 propagation headers. Introduce PROPAGATION_EXCLUDE_PORTS config (default "8123") and update HttpClientDoExecuteInterceptor to skip tracing for excluded ports. Requests to other ports continue to be traced normally. Verified with ClickHouse JDBC queries. --- CHANGES.md | 1 + .../v5/HttpClient5PluginConfig.java | 47 ++++ .../v5/HttpClientDoExecuteInterceptor.java | 61 ++++- .../HttpClientPropagationExcludePortTest.java | 244 ++++++++++++++++++ 4 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClient5PluginConfig.java create mode 100644 apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClientPropagationExcludePortTest.java diff --git a/CHANGES.md b/CHANGES.md index 27e5c01fde..47b9ac0d94 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ Release Notes. * Added support for Lettuce reactive Redis commands. * Add Spring AI 1.x plugin and GenAI layer. +* Fix httpclient-5.x plugin injecting sw8 propagation headers into ClickHouse HTTP requests (port 8123), causing HTTP 400. Add `PROPAGATION_EXCLUDE_PORTS` config to skip tracing (including header injection) for specified ports in the classic client interceptor. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClient5PluginConfig.java b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClient5PluginConfig.java new file mode 100644 index 0000000000..3b6aaf6aa9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClient5PluginConfig.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.httpclient.v5; + +import org.apache.skywalking.apm.agent.core.boot.PluginConfig; + +public class HttpClient5PluginConfig { + public static class Plugin { + @PluginConfig(root = HttpClient5PluginConfig.class) + public static class HttpClient5 { + /** + * Comma-separated list of destination ports whose outbound HTTP requests + * will be completely skipped by the classic client interceptor: no exit + * span is created and no SkyWalking propagation headers are injected. + * + *

Some HTTP-based database protocols (e.g. ClickHouse on port 8123) + * reject requests that contain unknown HTTP headers, returning HTTP 400. + * Adding such ports here prevents the agent from creating exit spans + * and from injecting the {@code sw8} tracing headers into those outbound + * requests, meaning these requests are completely untraced by SkyWalking, + * while leaving all other HTTP calls fully traced. + * + *

Default: {@code "8123"} (ClickHouse HTTP interface). + * + *

Example – also exclude port 9200 (Elasticsearch): + * {@code plugin.httpclient5.PROPAGATION_EXCLUDE_PORTS=8123,9200} + */ + public static String PROPAGATION_EXCLUDE_PORTS = "8123"; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClientDoExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClientDoExecuteInterceptor.java index d53eb7a246..238a745b69 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClientDoExecuteInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClientDoExecuteInterceptor.java @@ -37,12 +37,23 @@ import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; public abstract class HttpClientDoExecuteInterceptor implements InstanceMethodsAroundInterceptor { private static final String ERROR_URI = "/_blank"; private static final ILog LOGGER = LogManager.getLogger(HttpClientDoExecuteInterceptor.class); + /** + * Lazily-resolved set of ports that must not receive SkyWalking + * propagation headers. Built once from + * {@link HttpClient5PluginConfig.Plugin.HttpClient5#PROPAGATION_EXCLUDE_PORTS}. + */ + private volatile Set excludePortsCache; + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { @@ -77,7 +88,55 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr protected boolean skipIntercept(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes) { - return allArguments[1] == null || getHttpHost(objInst, method, allArguments, argumentsTypes) == null; + if (allArguments[1] == null) { + return true; + } + HttpHost host = getHttpHost(objInst, method, allArguments, argumentsTypes); + if (host == null) { + return true; + } + return isExcludedPort(port(host)); + } + + /** + * Returns {@code true} when {@code port} is listed in + * {@link HttpClient5PluginConfig.Plugin.HttpClient5#PROPAGATION_EXCLUDE_PORTS}. + * + *

The config value is parsed lazily and cached so that it is read after + * the agent has fully initialised its configuration subsystem. + */ + private boolean isExcludedPort(int port) { + if (port <= 0) { + return false; + } + if (excludePortsCache == null) { + synchronized (this) { + if (excludePortsCache == null) { + excludePortsCache = parseExcludePorts( + HttpClient5PluginConfig.Plugin.HttpClient5.PROPAGATION_EXCLUDE_PORTS); + } + } + } + return excludePortsCache.contains(port); + } + + private static Set parseExcludePorts(String raw) { + if (raw == null || raw.trim().isEmpty()) { + return Collections.emptySet(); + } + return Arrays.stream(raw.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .map(s -> { + try { + return Integer.parseInt(s); + } catch (NumberFormatException e) { + LOGGER.warn("Ignoring invalid port in PROPAGATION_EXCLUDE_PORTS: {}", s); + return -1; + } + }) + .filter(p -> p > 0) + .collect(Collectors.toSet()); } protected abstract HttpHost getHttpHost(EnhancedInstance objInst, Method method, Object[] allArguments, diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClientPropagationExcludePortTest.java b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClientPropagationExcludePortTest.java new file mode 100644 index 0000000000..717eb61a3e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpclient-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpclient/v5/HttpClientPropagationExcludePortTest.java @@ -0,0 +1,244 @@ +/* + * 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.httpclient.v5; + +import org.apache.hc.core5.http.ClassicHttpRequest; +import org.apache.hc.core5.http.ClassicHttpResponse; +import org.apache.hc.core5.http.HttpHost; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import java.net.URI; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Verifies that requests to ports listed in + * {@link HttpClient5PluginConfig.Plugin.HttpClient5#PROPAGATION_EXCLUDE_PORTS} + * are silently skipped (no span created, no {@code sw8} header injected). + * + *

This regression-covers the ClickHouse HTTP-interface issue: ClickHouse + * listens on port 8123 and rejects HTTP requests that carry unknown headers + * (such as the SkyWalking {@code sw8} propagation header), responding with + * HTTP 400 Bad Request. By excluding port 8123 the agent leaves those + * requests untouched while continuing to trace all other HTTP calls. + */ +@RunWith(TracingSegmentRunner.class) +public class HttpClientPropagationExcludePortTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @Mock + private HttpHost clickHouseHost; // port 8123 – should be excluded + @Mock + private HttpHost regularHost; // port 8080 – should be traced + @Mock + private ClassicHttpRequest request; + @Mock + private ClassicHttpResponse httpResponse; + @Mock + private EnhancedInstance enhancedInstance; + + private HttpClientDoExecuteInterceptor internalInterceptor; + private HttpClientDoExecuteInterceptor minimalInterceptor; + + private Object[] clickHouseArgs; + private Object[] regularArgs; + private Class[] argumentsType; + + @Before + public void setUp() throws Exception { + ServiceManager.INSTANCE.boot(); + + // Set the exclusion list to the default (includes 8123) + HttpClient5PluginConfig.Plugin.HttpClient5.PROPAGATION_EXCLUDE_PORTS = "8123"; + + internalInterceptor = new InternalClientDoExecuteInterceptor(); + minimalInterceptor = new MinimalClientDoExecuteInterceptor(); + + when(httpResponse.getCode()).thenReturn(200); + + // ClickHouse-like host on port 8123 + when(clickHouseHost.getHostName()).thenReturn("clickhouse-server"); + when(clickHouseHost.getSchemeName()).thenReturn("http"); + when(clickHouseHost.getPort()).thenReturn(8123); + + // Regular application host on port 8080 + when(regularHost.getHostName()).thenReturn("my-service"); + when(regularHost.getSchemeName()).thenReturn("http"); + when(regularHost.getPort()).thenReturn(8080); + + when(request.getUri()).thenReturn(new URI("http://my-service:8080/api/ping")); + when(request.getMethod()).thenReturn("GET"); + + clickHouseArgs = new Object[]{clickHouseHost, request}; + regularArgs = new Object[]{regularHost, request}; + argumentsType = new Class[]{HttpHost.class, ClassicHttpRequest.class}; + } + + // ----------------------------------------------------------------------- + // InternalHttpClient path + // ----------------------------------------------------------------------- + + /** + * Requests to port 8123 via {@code InternalHttpClient} must not produce a + * trace segment and must NOT set any propagation header on the request. + * + *

Before this fix the agent injected {@code sw8} (and two companion + * headers) into every outbound request regardless of the destination port. + * ClickHouse interprets unknown headers as malformed requests and returns + * HTTP 400, making all JDBC queries fail while the SkyWalking agent is + * attached. + */ + @Test + public void internalClient_requestToExcludedPort_noSpanAndNoHeaderInjected() throws Throwable { + internalInterceptor.beforeMethod(enhancedInstance, null, clickHouseArgs, argumentsType, null); + internalInterceptor.afterMethod(enhancedInstance, null, clickHouseArgs, argumentsType, httpResponse); + + List segments = segmentStorage.getTraceSegments(); + assertThat("No trace segment should be created for excluded port", segments.size(), is(0)); + verify(request, never()).setHeader(anyString(), anyString()); + } + + /** + * Requests to a non-excluded port via {@code InternalHttpClient} must still + * be traced and have propagation headers injected. + */ + @Test + public void internalClient_requestToRegularPort_spanCreatedAndHeadersInjected() throws Throwable { + internalInterceptor.beforeMethod(enhancedInstance, null, regularArgs, argumentsType, null); + internalInterceptor.afterMethod(enhancedInstance, null, regularArgs, argumentsType, httpResponse); + + List segments = segmentStorage.getTraceSegments(); + assertThat("A trace segment must be created for a non-excluded port", segments.size(), is(1)); + // sw8, sw8-correlation, sw8-x – exactly 3 propagation headers, consistent with existing tests + verify(request, org.mockito.Mockito.times(3)).setHeader(anyString(), anyString()); + } + + // ----------------------------------------------------------------------- + // MinimalHttpClient path + // ----------------------------------------------------------------------- + + /** + * Same assertion for the {@code MinimalHttpClient} code path. + */ + @Test + public void minimalClient_requestToExcludedPort_noSpanAndNoHeaderInjected() throws Throwable { + minimalInterceptor.beforeMethod(enhancedInstance, null, clickHouseArgs, argumentsType, null); + minimalInterceptor.afterMethod(enhancedInstance, null, clickHouseArgs, argumentsType, httpResponse); + + List segments = segmentStorage.getTraceSegments(); + assertThat("No trace segment should be created for excluded port", segments.size(), is(0)); + verify(request, never()).setHeader(anyString(), anyString()); + } + + /** + * Normal (non-excluded) port via {@code MinimalHttpClient} must still be + * traced. + */ + @Test + public void minimalClient_requestToRegularPort_spanCreatedAndHeadersInjected() throws Throwable { + minimalInterceptor.beforeMethod(enhancedInstance, null, regularArgs, argumentsType, null); + minimalInterceptor.afterMethod(enhancedInstance, null, regularArgs, argumentsType, httpResponse); + + List segments = segmentStorage.getTraceSegments(); + assertThat("A trace segment must be created for a non-excluded port", segments.size(), is(1)); + verify(request, org.mockito.Mockito.times(3)).setHeader(anyString(), anyString()); + } + + // ----------------------------------------------------------------------- + // Configuration edge cases + // ----------------------------------------------------------------------- + + /** + * When {@code PROPAGATION_EXCLUDE_PORTS} is cleared (empty string), every + * port – including 8123 – must be traced normally. + */ + @Test + public void whenExcludePortsEmpty_allPortsAreTraced() throws Throwable { + HttpClient5PluginConfig.Plugin.HttpClient5.PROPAGATION_EXCLUDE_PORTS = ""; + + // Use a fresh interceptor so the cache is not pre-populated + HttpClientDoExecuteInterceptor freshInterceptor = new MinimalClientDoExecuteInterceptor(); + freshInterceptor.beforeMethod(enhancedInstance, null, clickHouseArgs, argumentsType, null); + freshInterceptor.afterMethod(enhancedInstance, null, clickHouseArgs, argumentsType, httpResponse); + + List segments = segmentStorage.getTraceSegments(); + assertThat("Port 8123 should be traced when exclusion list is empty", segments.size(), is(1)); + } + + /** + * Multiple ports can be listed: verify that both excluded ports are silently + * skipped while a non-excluded port is still traced under the same config. + */ + @Test + public void multipleExcludedPorts_allSkippedAndNonExcludedStillTraced() throws Throwable { + HttpClient5PluginConfig.Plugin.HttpClient5.PROPAGATION_EXCLUDE_PORTS = "8123,9200"; + + HttpClientDoExecuteInterceptor freshInterceptor = new MinimalClientDoExecuteInterceptor(); + + // 8123 – must be excluded + freshInterceptor.beforeMethod(enhancedInstance, null, clickHouseArgs, argumentsType, null); + freshInterceptor.afterMethod(enhancedInstance, null, clickHouseArgs, argumentsType, httpResponse); + assertThat("Port 8123 should be excluded", segmentStorage.getTraceSegments().size(), is(0)); + + // 9200 (Elasticsearch) – must also be excluded + HttpHost esHost = org.mockito.Mockito.mock(HttpHost.class); + when(esHost.getHostName()).thenReturn("es-server"); + when(esHost.getSchemeName()).thenReturn("http"); + when(esHost.getPort()).thenReturn(9200); + Object[] esArgs = new Object[]{esHost, request}; + + freshInterceptor = new MinimalClientDoExecuteInterceptor(); + freshInterceptor.beforeMethod(enhancedInstance, null, esArgs, argumentsType, null); + freshInterceptor.afterMethod(enhancedInstance, null, esArgs, argumentsType, httpResponse); + assertThat("Port 9200 should also be excluded", segmentStorage.getTraceSegments().size(), is(0)); + + // 8080 (regular service) – must still be traced under the same multi-port config + freshInterceptor = new MinimalClientDoExecuteInterceptor(); + freshInterceptor.beforeMethod(enhancedInstance, null, regularArgs, argumentsType, null); + freshInterceptor.afterMethod(enhancedInstance, null, regularArgs, argumentsType, httpResponse); + assertThat("Non-excluded port 8080 must still produce a trace segment", + segmentStorage.getTraceSegments().size(), is(1)); + } +} From 233effa70f86f3d6d53dfc4b8a4aa4817143e58c Mon Sep 17 00:00:00 2001 From: liuhaolong10 <41176805+liuhaolong10@users.noreply.github.com> Date: Fri, 13 Mar 2026 10:37:13 +0800 Subject: [PATCH 097/114] Add Spring RabbitMQ plugin (#796) --- .github/workflows/plugins-jdk17-test.0.yaml | 1 + CHANGES.md | 1 + .../rabbitmq/RabbitMQConsumerInterceptor.java | 9 + .../apm-sdk-plugin/spring-plugins/pom.xml | 3 +- .../spring-rabbitmq-plugin/pom.xml | 46 +++++ .../SpringRabbitMQConsumerInterceptor.java | 146 +++++++++++++ ...SpringRabbitMQConsumerInstrumentation.java | 69 +++++++ .../src/main/resources/skywalking-plugin.def | 17 ++ ...RabbitMQSpringConsumerInterceptorTest.java | 192 ++++++++++++++++++ .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 1 + .../spring-rabbitmq-scenario/bin/startup.sh | 20 ++ .../config/expectedData.yaml | 165 +++++++++++++++ .../configuration.yml | 33 +++ .../spring-rabbitmq-scenario/pom.xml | 117 +++++++++++ .../src/main/assembly/assembly.xml | 41 ++++ .../testcase/spring/rabbitmq/Application.java | 30 +++ .../rabbitmq/config/RabbitMqConfig.java | 54 +++++ .../rabbitmq/controller/CaseController.java | 85 ++++++++ .../src/main/resources/application.yml | 29 +++ .../src/main/resources/log4j2.xml | 31 +++ .../support-version.list | 18 ++ 22 files changed, 1108 insertions(+), 1 deletion(-) create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/SpringRabbitMQConsumerInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/define/SpringRabbitMQConsumerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/RabbitMQSpringConsumerInterceptorTest.java create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/configuration.yml create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/pom.xml create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/Application.java create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/config/RabbitMqConfig.java create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/controller/CaseController.java create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/src/main/resources/application.yml create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/spring-rabbitmq-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk17-test.0.yaml b/.github/workflows/plugins-jdk17-test.0.yaml index 092fa2daae..74ae79f0fe 100644 --- a/.github/workflows/plugins-jdk17-test.0.yaml +++ b/.github/workflows/plugins-jdk17-test.0.yaml @@ -80,6 +80,7 @@ jobs: - jetty-11.x-scenario - jetty-10.x-scenario - spring-ai-1.x-scenario + - spring-rabbitmq-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 47b9ac0d94..e49c314aab 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ Release Notes. * Added support for Lettuce reactive Redis commands. * Add Spring AI 1.x plugin and GenAI layer. * Fix httpclient-5.x plugin injecting sw8 propagation headers into ClickHouse HTTP requests (port 8123), causing HTTP 400. Add `PROPAGATION_EXCLUDE_PORTS` config to skip tracing (including header injection) for specified ports in the classic client interceptor. +* Add Spring RabbitMQ 2.x - 4.x plugin. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/rabbitmq/RabbitMQConsumerInterceptor.java b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/rabbitmq/RabbitMQConsumerInterceptor.java index 50240c9729..3ac0caf121 100644 --- a/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/rabbitmq/RabbitMQConsumerInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/rabbitmq/RabbitMQConsumerInterceptor.java @@ -26,10 +26,19 @@ public class RabbitMQConsumerInterceptor implements InstanceMethodsAroundInterceptor { + public static final String SMLC_INTERNAL_CONSUMER = "org.springframework.amqp.rabbit.listener.BlockingQueueConsumer$InternalConsumer"; + public static final String DMLC_INTERNAL_CONSUMER = "org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer$SimpleConsumer"; + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { Consumer consumer = (Consumer) allArguments[6]; + if (consumer != null) { + String className = consumer.getClass().getName(); + if (SMLC_INTERNAL_CONSUMER.equals(className) || DMLC_INTERNAL_CONSUMER.equals(className)) { + return; + } + } allArguments[6] = new TracerConsumer(consumer, (String) objInst.getSkyWalkingDynamicField()); } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml index 5a307810b3..4326ec7354 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml @@ -46,10 +46,11 @@ spring-webflux-6.x-webclient-plugin resttemplate-commons spring-ai-1.x-plugin + spring-rabbitmq-plugin pom - apm-sdk-plugin + spring-plugins http://maven.apache.org diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/pom.xml new file mode 100644 index 0000000000..cb0c687268 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/pom.xml @@ -0,0 +1,46 @@ + + + + 4.0.0 + + + org.apache.skywalking + spring-plugins + 9.7.0-SNAPSHOT + + + apm-spring-rabbitmq-plugin + apm-spring-rabbitmq-plugin + jar + + + 3.0.0 + + + + + org.springframework.amqp + spring-rabbit + ${spring-rabbit.version} + provided + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/SpringRabbitMQConsumerInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/SpringRabbitMQConsumerInterceptor.java new file mode 100644 index 0000000000..29bf40599f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/SpringRabbitMQConsumerInterceptor.java @@ -0,0 +1,146 @@ +/* + * 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.spring.rabbitmq; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; + +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.core.MessageProperties; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; + +public class SpringRabbitMQConsumerInterceptor implements InstanceMethodsAroundInterceptorV2 { + public static final String OPERATE_NAME_PREFIX = "RabbitMQ/"; + public static final String CONSUMER_OPERATE_NAME_SUFFIX = "/Consumer"; + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInvocationContext context) throws Throwable { + Channel channel = (Channel) allArguments[0]; + + if (allArguments[1] instanceof Message) { + // Single message consume + Message message = (Message) allArguments[1]; + MessageProperties messageProperties = message.getMessageProperties(); + Map headers = messageProperties.getHeaders(); + + ContextCarrier contextCarrier = buildContextCarrier(headers); + String operationName = buildOperationName(messageProperties); + AbstractSpan activeSpan = ContextManager.createEntrySpan(operationName, contextCarrier); + + setSpanAttributes(activeSpan, channel, messageProperties); + } else if (allArguments[1] instanceof List) { + // Batch message consume + List messages = (List) allArguments[1]; + if (messages.isEmpty()) { + return; + } + + // Use the first message to create EntrySpan + Message firstMessage = (Message) messages.get(0); + MessageProperties firstMessageProperties = firstMessage.getMessageProperties(); + Map firstMessageHeaders = firstMessageProperties.getHeaders(); + + ContextCarrier contextCarrier = buildContextCarrier(firstMessageHeaders); + String operationName = buildOperationName(firstMessageProperties); + AbstractSpan activeSpan = ContextManager.createEntrySpan(operationName, contextCarrier); + + setSpanAttributes(activeSpan, channel, firstMessageProperties); + + // Extract trace context from remaining messages (skip first, already used for EntrySpan) + // to correlate all producer traces with this consumer span + for (int i = 1; i < messages.size(); i++) { + Object msg = messages.get(i); + if (msg instanceof Message) { + Message message = (Message) msg; + MessageProperties messageProperties = message.getMessageProperties(); + Map headers = messageProperties.getHeaders(); + + ContextCarrier carrier = buildContextCarrier(headers); + if (carrier.isValid()) { + ContextManager.extract(carrier); + } + } + } + } + } + + /** + * Build ContextCarrier from message headers + */ + private ContextCarrier buildContextCarrier(Map headers) { + ContextCarrier contextCarrier = new ContextCarrier(); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + Object value = headers.get(next.getHeadKey()); + if (value != null) { + next.setHeadValue(value.toString()); + } + } + return contextCarrier; + } + + private String buildOperationName(MessageProperties messageProperties) { + return OPERATE_NAME_PREFIX + "Topic/" + messageProperties.getReceivedExchange() + + "Queue/" + messageProperties.getReceivedRoutingKey() + + CONSUMER_OPERATE_NAME_SUFFIX; + } + + private void setSpanAttributes(AbstractSpan span, Channel channel, MessageProperties messageProperties) { + Connection connection = channel.getConnection(); + String serverUrl = connection.getAddress().getHostAddress() + ":" + connection.getPort(); + Tags.MQ_BROKER.set(span, serverUrl); + Tags.MQ_TOPIC.set(span, messageProperties.getReceivedExchange()); + Tags.MQ_QUEUE.set(span, messageProperties.getReceivedRoutingKey()); + span.setComponent(ComponentsDefine.RABBITMQ_CONSUMER); + span.setPeer(serverUrl); + SpanLayer.asMQ(span); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret, MethodInvocationContext context) throws Throwable { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { + if (ContextManager.isActive()) { + ContextManager.activeSpan().log(t); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/define/SpringRabbitMQConsumerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/define/SpringRabbitMQConsumerInstrumentation.java new file mode 100644 index 0000000000..b4a541adc8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/define/SpringRabbitMQConsumerInstrumentation.java @@ -0,0 +1,69 @@ +/* + * 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.spring.rabbitmq.define; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.DeclaredInstanceMethodsInterceptV2Point; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class SpringRabbitMQConsumerInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 { + public static final String ENHANCE_CLASS = "org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer"; + public static final String ENHANCE_METHOD = "executeListener"; + public static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.rabbitmq.SpringRabbitMQConsumerInterceptor"; + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { + return new InstanceMethodsInterceptV2Point[] { + new DeclaredInstanceMethodsInterceptV2Point() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override + public String getMethodsInterceptorV2() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..94d87de414 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-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. + +spring-rabbitmq=org.apache.skywalking.apm.plugin.spring.rabbitmq.define.SpringRabbitMQConsumerInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/RabbitMQSpringConsumerInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/RabbitMQSpringConsumerInterceptorTest.java new file mode 100644 index 0000000000..e29864204e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-rabbitmq-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/rabbitmq/RabbitMQSpringConsumerInterceptorTest.java @@ -0,0 +1,192 @@ +/* + * 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.spring.rabbitmq; + +import static org.hamcrest.CoreMatchers.is; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.skywalking.apm.agent.core.context.SW8CarrierItem; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.core.MessageProperties; + +import com.rabbitmq.client.Channel; +import com.rabbitmq.client.Connection; + +@RunWith(TracingSegmentRunner.class) +public class RabbitMQSpringConsumerInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + private SpringRabbitMQConsumerInterceptor rabbitMQConsumerInterceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + @Before + public void setUp() throws Exception { + rabbitMQConsumerInterceptor = new SpringRabbitMQConsumerInterceptor(); + } + + @Test + public void testRabbitMQConsumerInterceptorWithNilHeaders() throws Throwable { + Object[] args = prepareMockData(false); + rabbitMQConsumerInterceptor.beforeMethod(enhancedInstance, null, args, new Class[0], null); + rabbitMQConsumerInterceptor.afterMethod(enhancedInstance, null, args, new Class[0], null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void testRabbitMQConsumerInterceptor() throws Throwable { + Object[] args = prepareMockData(true); + rabbitMQConsumerInterceptor.beforeMethod(enhancedInstance, null, args, new Class[0], null); + rabbitMQConsumerInterceptor.afterMethod(enhancedInstance, null, args, new Class[0], null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void testBatchMessageConsumption() throws Throwable { + Object[] args = prepareMockBatchData(true); + rabbitMQConsumerInterceptor.beforeMethod(enhancedInstance, null, args, new Class[0], null); + rabbitMQConsumerInterceptor.afterMethod(enhancedInstance, null, args, new Class[0], null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void testEmptyBatchMessageConsumption() throws Throwable { + Channel channel = mock(Channel.class); + Connection connection = mock(Connection.class); + InetAddress address = mock(InetAddress.class); + + when(channel.getConnection()).thenReturn(connection); + when(connection.getAddress()).thenReturn(address); + when(address.getHostAddress()).thenReturn("127.0.0.1"); + when(connection.getPort()).thenReturn(5672); + + Object[] args = new Object[] {channel, new java.util.ArrayList()}; + rabbitMQConsumerInterceptor.beforeMethod(enhancedInstance, null, args, new Class[0], null); + rabbitMQConsumerInterceptor.afterMethod(enhancedInstance, null, args, new Class[0], null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(0)); + } + + private Object[] prepareMockData(boolean withHeaders) throws Exception { + Channel channel = mock(Channel.class); + Connection connection = mock(Connection.class); + InetAddress address = mock(InetAddress.class); + Message message = mock(Message.class); + MessageProperties messageProperties = mock(MessageProperties.class); + + when(channel.getConnection()).thenReturn(connection); + when(connection.getAddress()).thenReturn(address); + when(address.getHostAddress()).thenReturn("127.0.0.1"); + when(connection.getPort()).thenReturn(5672); + when(message.getMessageProperties()).thenReturn(messageProperties); + when(messageProperties.getReceivedExchange()).thenReturn("test-exchange"); + when(messageProperties.getReceivedRoutingKey()).thenReturn("test-routing-key"); + + if (withHeaders) { + Map headers = new HashMap<>(); + headers.put(SW8CarrierItem.HEADER_NAME, + "1-My40LjU=-MS4yLjM=-3-c2VydmljZQ==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA="); + when(messageProperties.getHeader(SW8CarrierItem.HEADER_NAME)) + .thenReturn(headers.get(SW8CarrierItem.HEADER_NAME)); + } + + return new Object[] {channel, message}; + } + + private Object[] prepareMockBatchData(boolean withHeaders) throws Exception { + Channel channel = mock(Channel.class); + Connection connection = mock(Connection.class); + InetAddress address = mock(InetAddress.class); + + when(channel.getConnection()).thenReturn(connection); + when(connection.getAddress()).thenReturn(address); + when(address.getHostAddress()).thenReturn("127.0.0.1"); + when(connection.getPort()).thenReturn(5672); + + Message message1 = mock(Message.class); + Message message2 = mock(Message.class); + Message message3 = mock(Message.class); + MessageProperties props1 = mock(MessageProperties.class); + MessageProperties props2 = mock(MessageProperties.class); + MessageProperties props3 = mock(MessageProperties.class); + + when(message1.getMessageProperties()).thenReturn(props1); + when(message2.getMessageProperties()).thenReturn(props2); + when(message3.getMessageProperties()).thenReturn(props3); + + when(props1.getReceivedExchange()).thenReturn("test-exchange"); + when(props1.getReceivedRoutingKey()).thenReturn("test-routing-key"); + when(props2.getReceivedExchange()).thenReturn("test-exchange"); + when(props2.getReceivedRoutingKey()).thenReturn("test-routing-key"); + when(props3.getReceivedExchange()).thenReturn("test-exchange"); + when(props3.getReceivedRoutingKey()).thenReturn("test-routing-key"); + + if (withHeaders) { + Map headers1 = new HashMap<>(); + headers1.put(SW8CarrierItem.HEADER_NAME, + "1-My40LjU=-MS4yLjM=-3-c2VydmljZQ==-aW5zdGFuY2U=-L2FwcA==-MTI3LjAuMC4xOjgwODA="); + when(props1.getHeader(SW8CarrierItem.HEADER_NAME)) + .thenReturn(headers1.get(SW8CarrierItem.HEADER_NAME)); + + Map headers2 = new HashMap<>(); + headers2.put(SW8CarrierItem.HEADER_NAME, + "1-NTY3Ljg=-OS4xMC4xMQ==-12-ZXJ2aWNlMg==-aW5zdGFuY2UyLU9hcHA=-MTI3LjAuMC4yOjgwODA="); + when(props2.getHeader(SW8CarrierItem.HEADER_NAME)) + .thenReturn(headers2.get(SW8CarrierItem.HEADER_NAME)); + + Map headers3 = new HashMap<>(); + headers3.put(SW8CarrierItem.HEADER_NAME, + "1-MTExLjIyMi4zMzM=-NDQ0LjU1NS42NjY=-MzQ1-ZXJ2aWNlMw==-aW5zdGFuY2UzLU9hcHA=-MTI3LjAuMC4zOjgwODA="); + when(props3.getHeader(SW8CarrierItem.HEADER_NAME)) + .thenReturn(headers3.get(SW8CarrierItem.HEADER_NAME)); + } + + List messages = new ArrayList<>(Arrays.asList(message1, message2, message3)); + return new Object[] {channel, messages}; + } +} 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 49d1cb9c8e..3764ae9716 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -114,6 +114,7 @@ - spring-core-patch - spring-kafka-1.x - spring-kafka-2.x +- spring-rabbitmq - spring-mvc-annotation - spring-mvc-annotation-3.x - spring-mvc-annotation-4.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index cdadd27422..1645c43b4e 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -80,6 +80,7 @@ metrics based on the tracing data. * [Spring-Kafka](https://github.com/spring-projects/spring-kafka) Spring Kafka Consumer 1.3.x -> 2.3.x (2.0.x and 2.1.x not tested and not recommended by [the official document](https://spring.io/projects/spring-kafka)) * [ActiveMQ](https://github.com/apache/activemq) 5.10.0 -> 5.15.4 * [RabbitMQ](https://www.rabbitmq.com/) 3.x-> 5.x + * [Spring-RabbitMQ](https://github.com/spring-projects/spring-amqp) 2.x -> 4.x * [Pulsar](http://pulsar.apache.org) 2.2.x -> 2.9.x * [NATS](https://github.com/nats-io/nats.java) 2.14.x -> 2.16.5 * [ActiveMQ-Artemis](https://github.com/apache/activemq) 2.30.0 -> 2.31.2 diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/bin/startup.sh b/test/plugin/scenarios/spring-rabbitmq-scenario/bin/startup.sh new file mode 100644 index 0000000000..f98cd90a75 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/bin/startup.sh @@ -0,0 +1,20 @@ +#!/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 -Dspring.rabbitmq.host=${RABBITMQ_HOST:-rabbitmq-server} -jar ${agent_opts} ${home}/../libs/spring-rabbitmq-scenario.jar & diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-rabbitmq-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..a9c4a431a2 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/config/expectedData.yaml @@ -0,0 +1,165 @@ +# 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: spring-rabbitmq-scenario + segmentSize: ge 4 + segments: + - segmentId: not null + spans: + - operationName: HEAD:/spring-rabbitmq-scenario/case/healthcheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-rabbitmq-scenario/case/healthcheck'} + - {key: http.method, value: HEAD} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: RabbitMQ/Topic/Queue/test/Producer + parentSpanId: 0 + spanId: 1 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 52 + isError: false + spanType: Exit + peer: not blank + tags: + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: test} + - {key: mq.topic, value: ''} + skipAnalysis: 'false' + - operationName: RabbitMQ/Topic/Queue/test-batch/Producer + parentSpanId: 0 + spanId: 2 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 52 + isError: false + spanType: Exit + peer: not blank + tags: + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: test-batch} + - {key: mq.topic, value: ''} + skipAnalysis: 'false' + - operationName: RabbitMQ/Topic/Queue/test-batch/Producer + parentSpanId: 0 + spanId: 3 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 52 + isError: false + spanType: Exit + peer: not blank + tags: + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: test-batch} + - {key: mq.topic, value: ''} + skipAnalysis: 'false' + - operationName: RabbitMQ/Topic/Queue/test-batch/Producer + parentSpanId: 0 + spanId: 4 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 52 + isError: false + spanType: Exit + peer: not blank + tags: + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: test-batch} + - {key: mq.topic, value: ''} + skipAnalysis: 'false' + - operationName: GET:/spring-rabbitmq-scenario/case/rabbitmq + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-rabbitmq-scenario/case/rabbitmq'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: RabbitMQ/Topic/Queue/test-batch/Consumer + parentSpanId: -1 + spanId: 0 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 53 + isError: false + spanType: Entry + peer: not blank + tags: + - {key: transmission.latency, value: ge 0} + - {key: mq.broker, value: not blank} + - {key: mq.topic, value: ''} + - {key: mq.queue, value: test-batch} + - {key: transmission.latency, value: ge 0} + - {key: transmission.latency, value: ge 0} + refs: + - {parentEndpoint: GET:/spring-rabbitmq-scenario/case/rabbitmq, networkAddress: not null, + refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-rabbitmq-scenario, traceId: not null} + - {parentEndpoint: GET:/spring-rabbitmq-scenario/case/rabbitmq, networkAddress: not null, + refType: CrossProcess, parentSpanId: 3, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-rabbitmq-scenario, traceId: not null} + - {parentEndpoint: GET:/spring-rabbitmq-scenario/case/rabbitmq, networkAddress: not null, + refType: CrossProcess, parentSpanId: 4, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-rabbitmq-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: RabbitMQ/Topic/Queue/test/Consumer + parentSpanId: -1 + spanId: 0 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 53 + isError: false + spanType: Entry + peer: not blank + tags: + - {key: transmission.latency, value: ge 0} + - {key: mq.broker, value: not blank} + - {key: mq.topic, value: ''} + - {key: mq.queue, value: test} + refs: + - {parentEndpoint: GET:/spring-rabbitmq-scenario/case/rabbitmq, networkAddress: not null, + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-rabbitmq-scenario, traceId: not null} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/configuration.yml b/test/plugin/scenarios/spring-rabbitmq-scenario/configuration.yml new file mode 100644 index 0000000000..31cb305bd1 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/configuration.yml @@ -0,0 +1,33 @@ +# 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/spring-rabbitmq-scenario/case/rabbitmq +healthCheck: http://localhost:8080/spring-rabbitmq-scenario/case/healthcheck +startScript: ./bin/startup.sh +environment: + - RABBITMQ_HOST=rabbitmq-server +depends_on: + - rabbitmq-server +dependencies: + rabbitmq-server: + image: rabbitmq:3.8.18 + hostname: rabbitmq-server + expose: + - 5672 + - 15672 + environment: + - RABBITMQ_DEFAULT_PASS=admin + - RABBITMQ_DEFAULT_USER=admin + - RABBITMQ_DEFAULT_VHOST=/ diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/pom.xml b/test/plugin/scenarios/spring-rabbitmq-scenario/pom.xml new file mode 100644 index 0000000000..0bf98a4869 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/pom.xml @@ -0,0 +1,117 @@ + + + + 4.0.0 + + org.apache.skywalking + spring-rabbitmq-scenario + 1.0-SNAPSHOT + + + UTF-8 + 17 + 3.8.1 + 3.0.0 + ${test.framework.version} + 2.19.0 + + + + + org.springframework.boot + spring-boot-starter-amqp + ${test.framework.version} + + + + org.springframework.boot + spring-boot-starter + ${test.framework.version} + + + spring-boot-starter-logging + org.springframework.boot + + + + + org.springframework.boot + spring-boot-starter-web + ${test.framework.version} + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + + + spring-rabbitmq-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${test.framework.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..0e51e5c531 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/spring-rabbitmq-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/Application.java b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/Application.java new file mode 100644 index 0000000000..9001ed22a9 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/Application.java @@ -0,0 +1,30 @@ +/* + * 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.testcase.spring.rabbitmq; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/config/RabbitMqConfig.java b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/config/RabbitMqConfig.java new file mode 100644 index 0000000000..a0de5ee428 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/config/RabbitMqConfig.java @@ -0,0 +1,54 @@ +/* + * 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.testcase.spring.rabbitmq.config; + +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitMqConfig { + + @Bean + public Queue testQueue() { + return new Queue("test", false); + } + + @Bean + public Queue testBatchQueue() { + return new Queue("test-batch", false); + } + + @Bean + public SimpleRabbitListenerContainerFactory batchRabbitListenerContainerFactory( + ConnectionFactory connectionFactory) { + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + factory.setConnectionFactory(connectionFactory); + // Enable batch listening mode + factory.setBatchListener(true); + factory.setConsumerBatchEnabled(true); + // Set batch size + factory.setBatchSize(3); + factory.setPrefetchCount(3); + factory.setReceiveTimeout(3000L); + return factory; + } +} diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/controller/CaseController.java b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/controller/CaseController.java new file mode 100644 index 0000000000..e143c51bf9 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/java/org/apache/skywalking/apm/testcase/spring/rabbitmq/controller/CaseController.java @@ -0,0 +1,85 @@ +/* + * 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.testcase.spring.rabbitmq.controller; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.core.MessageBuilder; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +public class CaseController { + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + private static final String QUEUE_NAME = "test"; + private static final String BATCH_QUEUE_NAME = "test-batch"; + + private static final String MESSAGE = "rabbitmq-testcase"; + + @Autowired + private RabbitTemplate rabbitTemplate; + + @RequestMapping("/rabbitmq") + @ResponseBody + public String send() { + LOGGER.info("Message being published -------------->" + MESSAGE); + rabbitTemplate.convertAndSend(QUEUE_NAME, MESSAGE); + LOGGER.info("Message has been published-------------->" + MESSAGE); + + // Also send batch messages to test batch consumption + LOGGER.info("Sending batch messages --------------"); + List messages = new ArrayList<>(); + for (int i = 0; i < 3; i++) { + Message message = MessageBuilder.withBody(("batch-message-" + i).getBytes()).build(); + messages.add(message); + } + for (Message message : messages) { + rabbitTemplate.send(BATCH_QUEUE_NAME, message); + } + LOGGER.info("Batch messages have been published--------------"); + + return "Success"; + } + + @RabbitListener(queues = QUEUE_NAME) + public void consumer(String message) { + LOGGER.info("Message Consumer received-------------->" + message); + } + + @RabbitListener(queues = BATCH_QUEUE_NAME, containerFactory = "batchRabbitListenerContainerFactory") + public void batchConsumer(List messages) { + LOGGER.info("Batch Consumer received " + messages.size() + " messages: " + messages); + } + + @RequestMapping("/healthcheck") + public String healthCheck() { + return "Success"; + } +} diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/resources/application.yml b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/resources/application.yml new file mode 100644 index 0000000000..5b93e6c91a --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/resources/application.yml @@ -0,0 +1,29 @@ +# +# 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 + servlet: + context-path: /spring-rabbitmq-scenario + +spring: + rabbitmq: + host: ${RABBITMQ_HOST:127.0.0.1} + port: 5672 + username: admin + password: admin + virtual-host: / diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..565fda00e0 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + diff --git a/test/plugin/scenarios/spring-rabbitmq-scenario/support-version.list b/test/plugin/scenarios/spring-rabbitmq-scenario/support-version.list new file mode 100644 index 0000000000..8c67d6f4a8 --- /dev/null +++ b/test/plugin/scenarios/spring-rabbitmq-scenario/support-version.list @@ -0,0 +1,18 @@ +# 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. + +3.0.0 +4.0.0 \ No newline at end of file From 2f1d9e94d6d1ac22d92f4e9c6905901fe646ffdf Mon Sep 17 00:00:00 2001 From: peachisai <2581009893@qq.com> Date: Mon, 16 Mar 2026 07:52:05 +0800 Subject: [PATCH 098/114] Fix the logic that was failing to record TTFR (#798) --- .../apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java index 9abb852187..e0c11c32ec 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java @@ -63,6 +63,8 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr return; } + ContextManager.getRuntimeContext().put(Constants.SPRING_AI_STREAM_START_TIME, System.currentTimeMillis()); + ChatOptions chatOptions = prompt.getOptions(); if (chatOptions == null) { return; @@ -72,8 +74,6 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr Tags.GEN_AI_TEMPERATURE.set(span, String.valueOf(chatOptions.getTemperature())); Tags.GEN_AI_TOP_K.set(span, String.valueOf(chatOptions.getTopK())); Tags.GEN_AI_TOP_P.set(span, String.valueOf(chatOptions.getTopP())); - - ContextManager.getRuntimeContext().put(Constants.SPRING_AI_STREAM_START_TIME, System.currentTimeMillis()); } @Override From ac0df43d7140e726eba9e5e5b1b75cf364c71dff Mon Sep 17 00:00:00 2001 From: peachisai <2581009893@qq.com> Date: Tue, 17 Mar 2026 22:08:08 +0800 Subject: [PATCH 099/114] Fix the tag key of ttfr to align with otlp semantic (#799) --- .../apache/skywalking/apm/agent/core/context/tag/Tags.java | 6 +++--- .../apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java | 2 +- .../spring-ai-1.x-scenario/config/expectedData.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java index 995b91f582..3d0b9f37cb 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java @@ -238,17 +238,17 @@ public static final class HTTP { /** * GEN_AI_STREAM_TTFR represents the time to first response (TTFR) for streaming operations. */ - public static final StringTag GEN_AI_STREAM_TTFR = new StringTag(40, "gen_ai.stream.ttfr"); + public static final StringTag GEN_AI_SERVER_TIME_TO_FIRST_TOKEN = new StringTag(40, "gen_ai.server.time_to_first_token"); /** * GEN_AI_INPUT_MESSAGES represents the chat history provided to the model as an input. */ - public static final StringTag GEN_AI_INPUT_MESSAGES = new StringTag(44, "gen_ai.input.messages"); + public static final StringTag GEN_AI_INPUT_MESSAGES = new StringTag(41, "gen_ai.input.messages"); /** * GEN_AI_OUTPUT_MESSAGES represents the messages returned by the model where each message represents a specific model response (choice, candidate). */ - public static final StringTag GEN_AI_OUTPUT_MESSAGES = new StringTag(45, "gen_ai.output.messages"); + public static final StringTag GEN_AI_OUTPUT_MESSAGES = new StringTag(42, "gen_ai.output.messages"); /** * Creates a {@code StringTag} with the given key and cache it, if it's created before, simply return it without diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java index e0c11c32ec..1674e82011 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java @@ -150,7 +150,7 @@ private void recordTtfrIfFirstToken(AbstractSpan span, Generation generation, St return; } if (state.firstResponseReceived.compareAndSet(false, true)) { - Tags.GEN_AI_STREAM_TTFR.set(span, String.valueOf(System.currentTimeMillis() - state.startTime)); + Tags.GEN_AI_SERVER_TIME_TO_FIRST_TOKEN.set(span, String.valueOf(System.currentTimeMillis() - state.startTime)); } } diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml index 161eb6e2f2..5f40e79a48 100644 --- a/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml @@ -116,7 +116,7 @@ segmentItems: - { key: gen_ai.request.temperature, value: '0.7' } - { key: gen_ai.request.top_k, value: null } - { key: gen_ai.request.top_p, value: '0.9' } - - { key: gen_ai.stream.ttfr, value: not null } + - { key: gen_ai.server.time_to_first_token, value: not null } - { key: gen_ai.response.id, value: 'chatcmpl-fc1b64d3' } - { key: gen_ai.response.model, value: gpt-4.1-2025-04-14 } - { key: gen_ai.response.finish_reasons, value: STOP } From b1351bcc826de086b65212c87b232524ef33a7c1 Mon Sep 17 00:00:00 2001 From: Guimu <30684111+daguimu@users.noreply.github.com> Date: Thu, 26 Mar 2026 19:55:22 +0800 Subject: [PATCH 100/114] Fix httpclient-4.x plugin injecting sw8 headers into excluded ports (#800) Add PROPAGATION_EXCLUDE_PORTS config to httpclient-4.x plugin, mirroring the existing httpclient-5.x feature. When configured, requests to listed ports skip span creation and header injection entirely, preventing HTTP 400 from servers like ClickHouse that reject unknown headers. Default is empty (opt-in). The ClickHouse E2E test sets it to 8123 explicitly. --- .../v4/HttpClientExecuteInterceptor.java | 71 +++++- .../HttpClientPropagationExcludePortTest.java | 203 ++++++++++++++++++ .../httpclient/HttpClientPluginConfig.java | 16 ++ apm-sniffer/config/agent.config | 4 +- changes/changes-9.5.0.md | 2 + .../config/expectedData.yaml | 9 - .../configuration.yml | 1 + 7 files changed, 293 insertions(+), 13 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientPropagationExcludePortTest.java diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java index b02de707af..24403bda2f 100644 --- a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientExecuteInterceptor.java @@ -22,6 +22,10 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URL; +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; @@ -34,6 +38,8 @@ import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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.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; @@ -43,12 +49,19 @@ public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterceptor { private static final String ERROR_URI = "/_blank"; + private static final ILog LOGGER = LogManager.getLogger(HttpClientExecuteInterceptor.class); + + /** + * Lazily-resolved set of ports that must not receive SkyWalking + * propagation headers. Built once from + * {@link HttpClientPluginConfig.Plugin.HttpClient#PROPAGATION_EXCLUDE_PORTS}. + */ + private volatile Set excludePortsCache; @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { - if (allArguments[0] == null || allArguments[1] == null) { - // illegal args, can't trace. ignore. + if (skipIntercept(allArguments)) { return; } final HttpHost httpHost = (HttpHost) allArguments[0]; @@ -82,7 +95,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { - if (allArguments[0] == null || allArguments[1] == null) { + if (skipIntercept(allArguments)) { return ret; } @@ -111,10 +124,62 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + if (skipIntercept(allArguments)) { + return; + } AbstractSpan activeSpan = ContextManager.activeSpan(); activeSpan.log(t); } + private boolean skipIntercept(Object[] allArguments) { + if (allArguments[0] == null || allArguments[1] == null) { + return true; + } + HttpHost httpHost = (HttpHost) allArguments[0]; + return isExcludedPort(port(httpHost)); + } + + /** + * Returns {@code true} when {@code port} is listed in + * {@link HttpClientPluginConfig.Plugin.HttpClient#PROPAGATION_EXCLUDE_PORTS}. + * + *

The config value is parsed lazily and cached so that it is read after + * the agent has fully initialised its configuration subsystem. + */ + private boolean isExcludedPort(int port) { + if (port <= 0) { + return false; + } + if (excludePortsCache == null) { + synchronized (this) { + if (excludePortsCache == null) { + excludePortsCache = parseExcludePorts( + HttpClientPluginConfig.Plugin.HttpClient.PROPAGATION_EXCLUDE_PORTS); + } + } + } + return excludePortsCache.contains(port); + } + + private static Set parseExcludePorts(String raw) { + if (raw == null || raw.trim().isEmpty()) { + return Collections.emptySet(); + } + return Arrays.stream(raw.split(",")) + .map(String::trim) + .filter(s -> !s.isEmpty()) + .map(s -> { + try { + return Integer.parseInt(s); + } catch (NumberFormatException e) { + LOGGER.warn("Ignoring invalid port in PROPAGATION_EXCLUDE_PORTS: {}", s); + return -1; + } + }) + .filter(p -> p > 0) + .collect(Collectors.toSet()); + } + private String getRequestURI(String uri) { if (isUrl(uri)) { String requestPath; diff --git a/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientPropagationExcludePortTest.java b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientPropagationExcludePortTest.java new file mode 100644 index 0000000000..9975bd92fc --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/httpClient-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/httpClient/v4/HttpClientPropagationExcludePortTest.java @@ -0,0 +1,203 @@ +/* + * 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.httpClient.v4; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.mock; + +import java.util.List; + +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.ProtocolVersion; +import org.apache.http.RequestLine; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpGet; +import org.apache.skywalking.apm.agent.core.boot.ServiceManager; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.plugin.httpclient.HttpClientPluginConfig; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +/** + * Verifies that requests to ports listed in + * {@link HttpClientPluginConfig.Plugin.HttpClient#PROPAGATION_EXCLUDE_PORTS} + * are silently skipped (no span created, no sw8 header injected). + */ +@RunWith(TracingSegmentRunner.class) +public class HttpClientPropagationExcludePortTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @Mock + private HttpHost clickHouseHost; + @Mock + private HttpHost regularHost; + @Mock + private HttpGet request; + @Mock + private HttpResponse httpResponse; + @Mock + private StatusLine statusLine; + @Mock + private EnhancedInstance enhancedInstance; + + private HttpClientExecuteInterceptor interceptor; + + private Object[] clickHouseArgs; + private Object[] regularArgs; + private Class[] argumentsType; + + @Before + public void setUp() throws Exception { + ServiceManager.INSTANCE.boot(); + + HttpClientPluginConfig.Plugin.HttpClient.PROPAGATION_EXCLUDE_PORTS = "8123"; + interceptor = new HttpClientExecuteInterceptor(); + + when(statusLine.getStatusCode()).thenReturn(200); + when(httpResponse.getStatusLine()).thenReturn(statusLine); + + RequestLine requestLine = new RequestLine() { + @Override + public String getMethod() { + return "GET"; + } + + @Override + public ProtocolVersion getProtocolVersion() { + return new ProtocolVersion("http", 1, 1); + } + + @Override + public String getUri() { + return "http://my-service:8080/api/ping"; + } + }; + when(request.getRequestLine()).thenReturn(requestLine); + + when(clickHouseHost.getHostName()).thenReturn("clickhouse-server"); + when(clickHouseHost.getSchemeName()).thenReturn("http"); + when(clickHouseHost.getPort()).thenReturn(8123); + + when(regularHost.getHostName()).thenReturn("my-service"); + when(regularHost.getSchemeName()).thenReturn("http"); + when(regularHost.getPort()).thenReturn(8080); + + clickHouseArgs = new Object[]{clickHouseHost, request}; + regularArgs = new Object[]{regularHost, request}; + argumentsType = new Class[]{HttpHost.class, HttpGet.class}; + } + + @Test + public void requestToExcludedPort_noSpanAndNoHeaderInjected() throws Throwable { + interceptor.beforeMethod(enhancedInstance, null, clickHouseArgs, argumentsType, null); + interceptor.afterMethod(enhancedInstance, null, clickHouseArgs, argumentsType, httpResponse); + + List segments = segmentStorage.getTraceSegments(); + assertThat(segments.size(), is(0)); + verify(request, never()).setHeader(anyString(), anyString()); + } + + @Test + public void requestToRegularPort_spanCreatedAndHeadersInjected() throws Throwable { + interceptor.beforeMethod(enhancedInstance, null, regularArgs, argumentsType, null); + interceptor.afterMethod(enhancedInstance, null, regularArgs, argumentsType, httpResponse); + + List segments = segmentStorage.getTraceSegments(); + assertThat(segments.size(), is(1)); + verify(request, times(3)).setHeader(anyString(), anyString()); + } + + @Test + public void whenExcludePortsEmpty_allPortsAreTraced() throws Throwable { + HttpClientPluginConfig.Plugin.HttpClient.PROPAGATION_EXCLUDE_PORTS = ""; + + HttpClientExecuteInterceptor freshInterceptor = new HttpClientExecuteInterceptor(); + freshInterceptor.beforeMethod(enhancedInstance, null, clickHouseArgs, argumentsType, null); + freshInterceptor.afterMethod(enhancedInstance, null, clickHouseArgs, argumentsType, httpResponse); + + List segments = segmentStorage.getTraceSegments(); + assertThat(segments.size(), is(1)); + } + + @Test + public void multipleExcludedPorts_allSkippedAndNonExcludedStillTraced() throws Throwable { + HttpClientPluginConfig.Plugin.HttpClient.PROPAGATION_EXCLUDE_PORTS = "8123,9200"; + + HttpClientExecuteInterceptor freshInterceptor = new HttpClientExecuteInterceptor(); + + // 8123 should be excluded + freshInterceptor.beforeMethod(enhancedInstance, null, clickHouseArgs, argumentsType, null); + freshInterceptor.afterMethod(enhancedInstance, null, clickHouseArgs, argumentsType, httpResponse); + assertThat(segmentStorage.getTraceSegments().size(), is(0)); + + // 9200 should also be excluded + HttpHost esHost = mock(HttpHost.class); + when(esHost.getHostName()).thenReturn("es-server"); + when(esHost.getSchemeName()).thenReturn("http"); + when(esHost.getPort()).thenReturn(9200); + Object[] esArgs = new Object[]{esHost, request}; + + freshInterceptor = new HttpClientExecuteInterceptor(); + HttpClientPluginConfig.Plugin.HttpClient.PROPAGATION_EXCLUDE_PORTS = "8123,9200"; + freshInterceptor.beforeMethod(enhancedInstance, null, esArgs, argumentsType, null); + freshInterceptor.afterMethod(enhancedInstance, null, esArgs, argumentsType, httpResponse); + assertThat(segmentStorage.getTraceSegments().size(), is(0)); + + // 8080 should still be traced + freshInterceptor = new HttpClientExecuteInterceptor(); + HttpClientPluginConfig.Plugin.HttpClient.PROPAGATION_EXCLUDE_PORTS = "8123,9200"; + freshInterceptor.beforeMethod(enhancedInstance, null, regularArgs, argumentsType, null); + freshInterceptor.afterMethod(enhancedInstance, null, regularArgs, argumentsType, httpResponse); + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + } + + @Test + public void excludedPort_handleMethodExceptionSkipped() throws Throwable { + interceptor.beforeMethod(enhancedInstance, null, clickHouseArgs, argumentsType, null); + interceptor.handleMethodException(enhancedInstance, null, clickHouseArgs, argumentsType, new RuntimeException("test")); + interceptor.afterMethod(enhancedInstance, null, clickHouseArgs, argumentsType, httpResponse); + + List segments = segmentStorage.getTraceSegments(); + assertThat(segments.size(), is(0)); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/httpclient-commons/src/main/java/org/apache/skywalking/apm/plugin/httpclient/HttpClientPluginConfig.java b/apm-sniffer/apm-sdk-plugin/httpclient-commons/src/main/java/org/apache/skywalking/apm/plugin/httpclient/HttpClientPluginConfig.java index 9a4a94cdb1..2c54e1b220 100644 --- a/apm-sniffer/apm-sdk-plugin/httpclient-commons/src/main/java/org/apache/skywalking/apm/plugin/httpclient/HttpClientPluginConfig.java +++ b/apm-sniffer/apm-sdk-plugin/httpclient-commons/src/main/java/org/apache/skywalking/apm/plugin/httpclient/HttpClientPluginConfig.java @@ -28,6 +28,22 @@ public static class HttpClient { * This config item controls that whether the HttpClient plugin should collect the parameters of the request. */ public static boolean COLLECT_HTTP_PARAMS = false; + + /** + * Comma-separated list of destination ports whose outbound HTTP requests + * will be completely skipped by the httpclient-4.x interceptor: no exit + * span is created and no SkyWalking propagation headers are injected. + * + *

Some HTTP-based database protocols (e.g. ClickHouse on port 8123) + * reject requests that contain unknown HTTP headers, returning HTTP 400. + * Adding such ports here prevents the agent from creating exit spans + * and from injecting the {@code sw8} tracing headers into those outbound + * requests. + * + *

Example – exclude ClickHouse and Elasticsearch ports: + * {@code plugin.httpclient.propagation_exclude_ports=8123,9200} + */ + public static String PROPAGATION_EXCLUDE_PORTS = ""; } @PluginConfig(root = HttpClientPluginConfig.class) diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index 84b5c41622..38c9bbf8d5 100755 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -218,8 +218,10 @@ plugin.jdkthreading.threading_class_prefixes=${SW_PLUGIN_JDKTHREADING_THREADING_ plugin.tomcat.collect_http_params=${SW_PLUGIN_TOMCAT_COLLECT_HTTP_PARAMS:false} # This config item controls that whether the SpringMVC plugin should collect the parameters of the request, when your Spring application is based on Tomcat, consider only setting either `plugin.tomcat.collect_http_params` or `plugin.springmvc.collect_http_params`. Also, activate implicitly in the profiled trace. plugin.springmvc.collect_http_params=${SW_PLUGIN_SPRINGMVC_COLLECT_HTTP_PARAMS:false} -# This config item controls that whether the HttpClient plugin should collect the parameters of the request +# This config item controls that whether the HttpClient plugin should collect the parameters of the request plugin.httpclient.collect_http_params=${SW_PLUGIN_HTTPCLIENT_COLLECT_HTTP_PARAMS:false} +# Comma-separated list of destination ports whose outbound HTTP requests will be completely skipped by the httpclient-4.x interceptor (no exit span created, no sw8 headers injected). +plugin.httpclient.propagation_exclude_ports=${SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS:} # When `COLLECT_HTTP_PARAMS` is enabled, how many characters to keep and send to the OAP backend, use negative values to keep and send the complete parameters, NB. this config item is added for the sake of performance. plugin.http.http_params_length_threshold=${SW_PLUGIN_HTTP_HTTP_PARAMS_LENGTH_THRESHOLD:1024} # When `include_http_headers` declares header names, this threshold controls the length limitation of all header values. use negative values to keep and send the complete headers. Note. this config item is added for the sake of performance. diff --git a/changes/changes-9.5.0.md b/changes/changes-9.5.0.md index 01ff913873..8a74ea3b82 100644 --- a/changes/changes-9.5.0.md +++ b/changes/changes-9.5.0.md @@ -21,6 +21,8 @@ Release Notes. enhanced by both SkyWalking and Spring AOP. * Build: Centralized plugin version management in the root POM and remove redundant declarations. * Support Spring Cloud Gateway 4.3.x. +* Add `PROPAGATION_EXCLUDE_PORTS` config to httpclient-4.x plugin to skip tracing and header injection for + specified ports (default: 8123), fixing ClickHouse HTTP 400 caused by injected sw8 headers. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/236?closed=1) diff --git a/test/plugin/scenarios/clickhouse-0.3.1-scenario/config/expectedData.yaml b/test/plugin/scenarios/clickhouse-0.3.1-scenario/config/expectedData.yaml index 13111717cb..3702b46778 100644 --- a/test/plugin/scenarios/clickhouse-0.3.1-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/clickhouse-0.3.1-scenario/config/expectedData.yaml @@ -53,7 +53,6 @@ segmentItems: - {key: db.type, value: ClickHouse} - {key: db.instance, value: system} - {key: db.statement, value: 'select timezone(), version()'} - - {key: http.status_code, value: '200'} - operationName: ClickHouse/JDBC/Statement/executeQuery operationId: 0 parentSpanId: 0 @@ -70,7 +69,6 @@ segmentItems: - {key: db.type, value: ClickHouse} - {key: db.instance, value: system} - {key: db.statement, value: SELECT * FROM clusters} - - {key: http.status_code, value: '200'} - operationName: ClickHouse/JDBC/Statement/execute operationId: 0 parentSpanId: 0 @@ -87,7 +85,6 @@ segmentItems: - {key: db.type, value: ClickHouse} - {key: db.instance, value: system} - {key: db.statement, value: SELECT 1} - - {key: http.status_code, value: '200'} - operationName: ClickHouse/JDBC/Connection/close operationId: 0 parentSpanId: 0 @@ -120,7 +117,6 @@ segmentItems: - {key: db.type, value: ClickHouse} - {key: db.instance, value: system} - {key: db.statement, value: 'select timezone(), version()'} - - {key: http.status_code, value: '200'} - operationName: ClickHouse/JDBC/PreparedStatement/executeQuery operationId: 0 parentSpanId: 0 @@ -137,7 +133,6 @@ segmentItems: - {key: db.type, value: ClickHouse} - {key: db.instance, value: system} - {key: db.statement, value: SELECT * FROM clusters} - - {key: http.status_code, value: '200'} - operationName: ClickHouse/JDBC/Statement/execute operationId: 0 parentSpanId: 0 @@ -154,7 +149,6 @@ segmentItems: - {key: db.type, value: ClickHouse} - {key: db.instance, value: system} - {key: db.statement, value: SELECT 1} - - {key: http.status_code, value: '200'} - operationName: ClickHouse/JDBC/Connection/close operationId: 0 parentSpanId: 0 @@ -187,7 +181,6 @@ segmentItems: - {key: db.type, value: ClickHouse} - {key: db.instance, value: system} - {key: db.statement, value: 'select timezone(), version()'} - - {key: http.status_code, value: '200'} - operationName: ClickHouse/JDBC/PreparedStatement/executeQuery operationId: 0 parentSpanId: 0 @@ -205,7 +198,6 @@ segmentItems: - {key: db.instance, value: system} - {key: db.statement, value: 'SELECT * FROM clusters WHERE cluster = ?'} - {key: db.sql.parameters, value: '[1]'} - - {key: http.status_code, value: '200'} - operationName: ClickHouse/JDBC/Statement/execute operationId: 0 parentSpanId: 0 @@ -222,7 +214,6 @@ segmentItems: - {key: db.type, value: ClickHouse} - {key: db.instance, value: system} - {key: db.statement, value: SELECT 1} - - {key: http.status_code, value: '200'} - operationName: ClickHouse/JDBC/Connection/close operationId: 0 parentSpanId: 0 diff --git a/test/plugin/scenarios/clickhouse-0.3.1-scenario/configuration.yml b/test/plugin/scenarios/clickhouse-0.3.1-scenario/configuration.yml index d98a13101c..3cfee72d53 100644 --- a/test/plugin/scenarios/clickhouse-0.3.1-scenario/configuration.yml +++ b/test/plugin/scenarios/clickhouse-0.3.1-scenario/configuration.yml @@ -20,6 +20,7 @@ healthCheck: http://localhost:8080/clickhouse-scenario/case/healthCheck startScript: ./bin/startup.sh environment: - SW_JDBC_TRACE_SQL_PARAMETERS=true + - SW_PLUGIN_HTTPCLIENT_PROPAGATION_EXCLUDE_PORTS=8123 depends_on: - clickhouse-server dependencies: From bc1bc3e495b1bbd9c8e938ab0c646ab2e3d5904f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Wed, 8 Apr 2026 22:43:33 +0800 Subject: [PATCH 101/114] Extend plugin test coverage for newer framework versions (#801) * Extend MySQL plugin to support MySQL Connector/J 8.4.0 and 9.x (9.0 -> 9.6). * Extend MariaDB plugin to support MariaDB Connector/J 2.7.x. * Extend MongoDB 4.x plugin to support MongoDB Java Driver 4.2 -> 4.10. Fix db.bind_vars extraction for driver 4.9+ where InsertOperation/DeleteOperation/UpdateOperation classes were removed. * Extend Feign plugin to support OpenFeign 10.x, 11.x, 12.1. * Extend Undertow plugin to support Undertow 2.1.x, 2.2.x, 2.3.x. * Extend GraphQL plugin to support graphql-java 18 -> 24 (20+ requires JDK 17). * Extend Spring Kafka plugin to support Spring Kafka 2.4 -> 2.9 and 3.0 -> 3.3. * Enhance test/plugin/run.sh to support extra Maven properties per version in support-version.list (format: version,key=value). --- .claude/skills/compile/SKILL.md | 156 +++ .claude/skills/new-plugin/SKILL.md | 1124 +++++++++++++++++ .github/workflows/plugins-jdk17-test.0.yaml | 3 + .github/workflows/plugins-test.3.yaml | 1 + CHANGES.md | 8 + apm-sniffer/apm-sdk-plugin/CLAUDE.md | 4 + .../v4/support/LegacyOperationHelper.java | 59 + .../v4/support/MongoOperationHelper.java | 45 +- .../service-agent/java-agent/Claude-Skills.md | 64 + .../service-agent/java-agent/Plugin-test.md | 10 + .../java-agent/Supported-list.md | 14 +- docs/menu.yml | 2 + test/plugin/run.sh | 17 +- .../feign-scenario/support-version.list | 3 + .../support-version.list | 3 + .../graphql-20plus-scenario/bin/startup.sh | 21 + .../config/expectedData.yaml | 88 ++ .../graphql-20plus-scenario/configuration.yml | 20 + .../scenarios/graphql-20plus-scenario/pom.xml | 117 ++ .../src/main/assembly/assembly.xml | 41 + .../apm/testcase/graphql/Application.java | 29 + .../graphql/configuration/GraphSchema.java | 120 ++ .../graphql/controller/CaseController.java | 53 + .../apm/testcase/graphql/data/User.java | 26 + .../src/main/resources/application.yml | 20 + .../support-version.list | 23 + .../mariadb-scenario/support-version.list | 1 + .../mongodb-4.x-scenario/support-version.list | 11 +- .../mysql-9.x-scenario/bin/startup.sh | 21 + .../config/expectedData.yaml | 151 +++ .../mysql-9.x-scenario/configuration.yml | 32 + .../scenarios/mysql-9.x-scenario/pom.xml | 123 ++ .../src/main/assembly/assembly.xml | 41 + .../apm/testcase/mysql/Application.java | 34 + .../apm/testcase/mysql/MysqlConfig.java | 58 + .../apm/testcase/mysql/SQLExecutor.java | 88 ++ .../mysql/controller/CaseController.java | 71 ++ .../src/main/resources/application.yaml | 23 + .../src/main/resources/jdbc.properties | 18 + .../src/main/resources/log4j2.xml | 30 + .../mysql-9.x-scenario/support-version.list | 25 + .../mysql-scenario/support-version.list | 2 + .../configuration.yml | 2 +- .../configuration.yml | 2 +- .../configuration.yml | 2 +- .../spring-kafka-2.3.x-scenario/pom.xml | 13 +- .../support-version.list | 9 + .../spring-kafka-3.x-scenario/bin/startup.sh | 21 + .../config/expectedData.yaml | 123 ++ .../configuration.yml | 39 + .../spring-kafka-3.x-scenario/pom.xml | 134 ++ .../src/main/assembly/assembly.xml | 41 + .../testcase/spring/kafka/Application.java | 30 + .../kafka/controller/CaseController.java | 159 +++ .../src/main/resources/application.properties | 19 + .../src/main/resources/log4j2.xml | 30 + .../support-version.list | 22 + .../undertow-2.3.x-scenario/bin/startup.sh | 21 + .../config/expectedData.yaml | 142 +++ .../undertow-2.3.x-scenario/configuration.yml | 20 + .../scenarios/undertow-2.3.x-scenario/pom.xml | 118 ++ .../src/main/assembly/assembly.xml | 41 + .../amp/testcase/undertow/Application.java | 94 ++ .../support-version.list | 18 + .../undertow-scenario/support-version.list | 3 + 65 files changed, 3864 insertions(+), 39 deletions(-) create mode 100644 .claude/skills/compile/SKILL.md create mode 100644 .claude/skills/new-plugin/SKILL.md create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/LegacyOperationHelper.java create mode 100644 docs/en/setup/service-agent/java-agent/Claude-Skills.md create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/configuration.yml create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/pom.xml create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/Application.java create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/configuration/GraphSchema.java create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/controller/CaseController.java create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/data/User.java create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/src/main/resources/application.yml create mode 100644 test/plugin/scenarios/graphql-20plus-scenario/support-version.list create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/Application.java create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/MysqlConfig.java create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/SQLExecutor.java create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/controller/CaseController.java create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/jdbc.properties create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/mysql-9.x-scenario/support-version.list create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring/kafka/Application.java create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring/kafka/controller/CaseController.java create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/resources/application.properties create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/spring-kafka-3.x-scenario/support-version.list create mode 100644 test/plugin/scenarios/undertow-2.3.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/undertow-2.3.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/undertow-2.3.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/undertow-2.3.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/undertow-2.3.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/undertow-2.3.x-scenario/src/main/java/org/apache/skywalking/amp/testcase/undertow/Application.java create mode 100644 test/plugin/scenarios/undertow-2.3.x-scenario/support-version.list diff --git a/.claude/skills/compile/SKILL.md b/.claude/skills/compile/SKILL.md new file mode 100644 index 0000000000..caebde530a --- /dev/null +++ b/.claude/skills/compile/SKILL.md @@ -0,0 +1,156 @@ +--- +name: compile +description: Build the SkyWalking Java agent — full build, skip tests, single module, or plugin test scenarios +user-invocable: true +allowed-tools: Bash, Read, Glob, Grep +--- + +# Compile SkyWalking Java Agent + +Build the project based on user request. Detect what they want to build and run the appropriate command. + +## Prerequisites + +- JDK 17, 21, or 25 (JDK 8 is supported at runtime but JDK 17+ is needed to compile) +- Maven is bundled as `./mvnw` (Maven wrapper) +- Git submodules must be initialized for protocol definitions + +Check JDK version first: +```bash +java -version +``` + +If submodules are not initialized: +```bash +git submodule init && git submodule update +``` + +## Build Commands + +### Full build (with tests) +```bash +./mvnw clean package -Pall +``` + +### Full build (skip tests — recommended for development) +```bash +./mvnw clean package -Dmaven.test.skip=true +``` + +### CI build (with javadoc verification) +```bash +./mvnw clean verify install javadoc:javadoc -Dmaven.test.skip=true +``` + +### Build a single plugin module +```bash +./mvnw clean package -pl apm-sniffer/apm-sdk-plugin/{plugin-name} -am -Dmaven.test.skip=true +``` +The `-am` flag builds required dependencies. Replace `{plugin-name}` with the actual plugin directory name. + +### Run checkstyle only +```bash +./mvnw checkstyle:check +``` + +### Run unit tests for a single module +```bash +./mvnw test -pl apm-sniffer/apm-sdk-plugin/{plugin-name} +``` + +### Build agent distribution only (after full build) +The built agent is in `skywalking-agent/` directory after a full build. + +### Run a plugin E2E test scenario + +The E2E test framework has a **two-phase build** (matching CI): + +**Phase 1 — Build agent + test tools + Docker images (one-time setup):** +```bash +# Build the agent (JDK 17+ required) +./mvnw clean package -Dmaven.test.skip=true + +# Switch to JDK 8 to build test tools and Docker images +# The test/plugin/pom.xml builds: runner-helper, agent-test-tools, JVM/Tomcat container images +export JAVA_HOME=$(/usr/libexec/java_home -v 8) +export PATH=$JAVA_HOME/bin:$PATH + +./mvnw --batch-mode -f test/plugin/pom.xml \ + -Dmaven.test.skip \ + -Dbase_image_java=eclipse-temurin:8-jdk \ + -Dbase_image_tomcat=tomcat:8.5-jdk8-openjdk \ + -Dcontainer_image_version=1.0.0 \ + clean package +``` + +This builds `skywalking/agent-test-jvm:1.0.0` and `skywalking/agent-test-tomcat:1.0.0` Docker images, +plus `test/plugin/dist/plugin-runner-helper.jar` and `test/plugin/agent-test-tools/dist/` (mock-collector, validator). + +**Phase 2 — Run test scenarios (per scenario):** +```bash +# Use JDK 8 (matching CI). JDK 17 works for runner-helper but JDK 8 matches CI exactly. +export JAVA_HOME=$(/usr/libexec/java_home -v 8) +export PATH=$JAVA_HOME/bin:$PATH + +# Run WITHOUT -f (reuses pre-built tools and images from Phase 1) +bash ./test/plugin/run.sh --debug {scenario-name} +``` + +**IMPORTANT flags:** +- `--debug` — keeps workspace with logs and `actualData.yaml` for inspection after test +- `-f` (force) — rebuilds ALL test tools and Docker images from scratch. **Do NOT use** if Phase 1 already completed — it re-clones `skywalking-agent-test-tool` from GitHub and rebuilds everything, which is slow and may fail due to network issues. +- Without `-f` — reuses existing tools/images. This is the normal way to run tests. + +**Key rules:** +- Run scenarios **one at a time** — they share Docker ports (8080, etc.) and will conflict if parallel +- JDK 8 test scenarios use `eclipse-temurin:8-jdk` base image +- JDK 17 test scenarios (in `plugins-jdk17-test` workflows) use `eclipse-temurin:17-jdk` base image +- After a test, check `test/plugin/workspace/{scenario}/{version}/data/actualData.yaml` vs `expectedData.yaml` for debugging failures +- Check `test/plugin/workspace/{scenario}/{version}/logs/` for container logs + +**Diagnosing "startup script not exists" failures:** +This error means the scenario ZIP wasn't built or copied into the container. The root cause is almost always a **silent Maven build failure** — `run.sh` uses `mvnw -q` (quiet mode) which hides errors. Common causes: +1. **Maven Central network timeout** — downloading a new library version fails silently. The `mvnw clean package` exits non-zero but the `-q` flag hides the error, and `run.sh` continues with missing artifacts. +2. **Docker Hub timeout** — pulling dependency images (mongo, mysql, kafka, zookeeper) fails with EOF/TLS errors. +3. **Killed previous run** — if a prior parallel run was killed mid-execution, leftover state in `test/plugin/workspace/` can interfere. Always `rm -rf test/plugin/workspace/{scenario}` before rerunning. + +To debug: run the Maven build manually in the scenario directory with verbose output: +```bash +cd test/plugin/scenarios/{scenario-name} +../../../../mvnw clean package -Dtest.framework.version={version} -Dmaven.test.skip=true +``` +If this succeeds but `run.sh` fails, it's likely a transient Maven Central network issue. Pre-download dependencies first: +```bash +# Pre-warm Maven cache for all versions before running tests +for v in $(grep -v '^#' test/plugin/scenarios/{scenario}/support-version.list | grep -v '^$'); do + cd test/plugin/scenarios/{scenario} + ../../../../mvnw dependency:resolve -Dtest.framework.version=$v -q + cd - +done +``` + +**Pre-pulling Docker dependency images:** +Scenarios with `dependencies:` in `configuration.yml` need external Docker images. Pre-pull them before running tests to avoid mid-test Docker Hub failures: +```bash +# Check what images a scenario needs +grep "image:" test/plugin/scenarios/{scenario}/configuration.yml +# Pull them +docker pull {image:tag} +``` + +### Generate protobuf sources (needed before IDE import) +```bash +./mvnw compile -Dmaven.test.skip=true +``` +Then mark `*/target/generated-sources/protobuf/java` and `*/target/generated-sources/protobuf/grpc-java` as generated source folders in your IDE. + +## Common Issues + +- **Submodule not initialized**: If proto files are missing, run `git submodule init && git submodule update` +- **Wrong JDK version**: Agent build requires JDK 17+. Test tools build (test/plugin/pom.xml) works best with JDK 8. Check with `java -version`. +- **Checkstyle failures**: Run `./mvnw checkstyle:check` to see violations. Common: star imports, unused imports, System.out.println, missing @Override. +- **Test scenario Docker issues**: Ensure Docker daemon is running. Use `--debug` flag to inspect `actualData.yaml`. +- **`run.sh -f` fails on agent-test-tools**: The `-f` flag clones `skywalking-agent-test-tool` from GitHub and rebuilds from source. If GitHub is slow or unreachable, this fails. Solution: run Phase 1 build separately (see above), then use `run.sh` without `-f`. +- **Lombok errors in runner-helper on JDK 25**: The test framework uses Lombok 1.18.20 which doesn't support JDK 25. Use JDK 8 or JDK 17 for building and running test tools. +- **"startup script not exists" inside container**: The scenario ZIP wasn't built or copied correctly. Check that `mvnw clean package` succeeds in the scenario directory and produces both a `.jar` and `.zip` in `target/`. +- **Port conflicts**: Never run multiple E2E scenarios simultaneously — they all bind to the same Docker ports. diff --git a/.claude/skills/new-plugin/SKILL.md b/.claude/skills/new-plugin/SKILL.md new file mode 100644 index 0000000000..08dc73d0f1 --- /dev/null +++ b/.claude/skills/new-plugin/SKILL.md @@ -0,0 +1,1124 @@ +--- +name: new-plugin +description: Develop a new SkyWalking Java agent plugin — instrumentation, interceptor, tracing/meter, tests, and all boilerplate +user-invocable: true +allowed-tools: Read, Write, Edit, Glob, Grep, Bash, Agent +--- + +# SkyWalking Java Agent Plugin Development + +Develop a new plugin for the Apache SkyWalking Java Agent. Ask the user what library/framework to instrument and what to observe (tracing, metrics, or both), then generate all required files. + +## Step 0 - Gather Requirements + +Ask the user: +1. **Target library/framework** and version range (e.g., "Jedis 3.x-4.x", "Spring Kafka 2.7+") +2. **Observation type**: tracing plugin, meter plugin, or both +3. **Plugin category**: SDK plugin (default), bootstrap plugin, or optional plugin +4. **Span type needed**: Entry (server/consumer), Exit (client/producer), Local (internal), or combination + +If the user already provided this info, skip asking. + +## Step 1 - Understand the Library and Identify Interception Points + +This is the most critical step. Do NOT jump to picking method names. Follow these phases in order. + +### Phase 1: Understand How the Library Is Used + +Read the target library's documentation, quickstart guides, or sample code. Understand the **user-facing API** — how developers create clients, make calls, and handle responses. This tells you: +- What objects are long-lived (clients, connections, pools) vs. per-request (requests, commands) +- Where configuration lives (server address, credentials, timeouts) +- Whether the library is sync, async, or reactive +- Whether it uses callbacks, futures, or blocking calls + +Example thought process for a Redis client: +``` +User creates: RedisClient client = RedisClient.create("redis://localhost:6379"); +User connects: StatefulRedisConnection conn = client.connect(); +User executes: conn.sync().get("key"); // or conn.async().get("key") +``` +This tells you: connection holds the server address, commands are executed on the connection. + +### Phase 2: Trace the Execution Flow + +Starting from the user-facing API, trace inward through the library source code to understand the execution workflow: +1. What happens when the user calls the API method? +2. Where does the request object get built? +3. Where is the actual network I/O or dispatch? +4. Where is the response available? +5. For RPC/MQ: where are headers/metadata accessible for inject/extract? + +**Key question at each point:** What data is directly accessible as method arguments, return values, or fields on `this`? You want interception points where you can read the data you need **without reflection**. + +### Phase 3: Choose Interception Points + +Pick interception points based on these principles: + +**Principle 1: Data accessibility without reflection.** +Choose methods where the information you need (peer address, operation name, request/response details, headers for inject/extract) is directly available as method arguments, return values, or accessible through the `this` object's public API. **Never use reflection to read private fields.** If the data is not accessible at one method, look at a different point in the execution flow. + +**Principle 2: Use `EnhancedInstance` dynamic field to propagate context inside the library.** +This is the primary mechanism for passing data between interception points. The agent adds a dynamic field to every enhanced class via `EnhancedInstance`. Use it to: +- Store server address (peer) at connection/client creation time, retrieve it at command execution time +- Store request info at request-build time, retrieve it at send time +- Pass span references from the initiating method to the completion callback + +**Do NOT use `Map` or other caches to store per-instance context.** Always use the dynamic field on the relevant `EnhancedInstance`. Maps introduce memory leaks, concurrency issues, and are slower than the direct field access that `EnhancedInstance` provides. + +**Principle 3: Intercept the minimal set of methods.** +Prefer one well-chosen interception point over many surface-level ones. If a library has 20 command methods that all flow through a single `dispatch()` method internally, intercept `dispatch()` — not all 20. + +**Principle 4: Pick points where you can do inject/extract for cross-process propagation.** +For RPC/HTTP/MQ plugins, you need to inject trace context into outgoing requests (ExitSpan) or extract from incoming requests (EntrySpan). The interception point MUST be where headers/metadata are writable (inject) or readable (extract). If headers are not accessible at the execution method, look for: +- A request builder/decorator stage where headers can be added +- A channel/transport layer where metadata is attached +- A message properties object accessible from the method arguments + +**Principle 5: Consider the span lifecycle across threads.** +If the library dispatches work asynchronously: +- Identify where the work is submitted (original thread) and where the result arrives (callback/future thread) +- You may need interception points in both threads +- Use `EnhancedInstance` dynamic field on the task/callback/future object to carry the span or `ContextSnapshot` across the thread boundary +- Use `prepareForAsync()` / `asyncFinish()` if the span must stay open across threads + +### Phase 4: Map Out the Interception Plan + +Before writing code, create a clear plan listing: + +| Target Class | Method/Constructor | What to Do | Data Available | +|---|---|---|---| +| `XxxClient` | constructor | Store peer address in dynamic field | host, port from args | +| `XxxConnection` | `execute(Command)` | Create ExitSpan, inject carrier into command headers | command name, peer from dynamic field | +| `XxxResponseHandler` | `onComplete(Response)` | Set response tags, stop span or asyncFinish | status code, error from args | + +For each interception point, verify: +- [ ] The data I need is readable from method args, `this`, or `EnhancedInstance` dynamic field — no reflection needed +- [ ] For inject: I can write headers/metadata through a public API on a method argument +- [ ] For extract: I can read headers/metadata through a public API on a method argument +- [ ] The `this` object (or a method argument) will be enhanced as `EnhancedInstance`, so I can use the dynamic field + +### Choosing Span Type + +| Scenario | Span Type | Requires | +|----------|-----------|----------| +| Receiving requests (HTTP server, MQ consumer, RPC provider) | EntrySpan | Extract ContextCarrier from incoming headers | +| Making outgoing calls (HTTP client, DB, cache, MQ producer, RPC consumer) | ExitSpan | Peer address; inject ContextCarrier into outgoing headers (for RPC/HTTP/MQ) | +| Internal processing (annotation-driven, local logic) | LocalSpan | Nothing extra | + +### For Meter Plugins + +Meter plugins follow the same understand-then-intercept process, but the goal is to find objects that expose numeric state: +- **Gauges**: Intercept the creation of pool/executor/connection-manager objects. Register a `MeterFactory.gauge()` with a supplier lambda that calls the object's own getter methods (e.g., `pool.getActiveCount()`). Store the gauge reference in the dynamic field if needed. +- **Counters**: Intercept execution methods and call `counter.increment()` on each invocation. +- **Histograms**: Intercept methods where duration or size is computable (measure between before/after, or read from response). + +### Check Existing Plugins for Reference + +Before writing a new plugin, check if a similar library already has a plugin: +``` +apm-sniffer/apm-sdk-plugin/ # 70+ standard plugins +apm-sniffer/optional-plugins/ # Optional plugins +apm-sniffer/bootstrap-plugins/ # JDK-level plugins +``` + +Similar libraries often share execution patterns. Study how an existing plugin for a similar library solved the same problems — especially how it chains dynamic fields across multiple interception points and where it does inject/extract. + +### Verify Against Actual Source Code — Never Speculate + +**This applies to both new plugin development AND extending existing plugins to newer library versions.** + +When assessing whether a plugin works with a new library version, or when choosing interception points for a new plugin, you MUST read the **actual source code** of the target library at the specific version. Do NOT rely on: +- Version number assumptions ("it's still 4.x so it should be compatible") +- Changelog summaries (they don't list every internal class rename or method removal) +- General knowledge about the library's public API (plugins intercept internal classes, which change without notice) + +**What to verify for each intercepted class/method:** +1. Does the target class still exist at the exact FQCN? (internal classes get renamed, extracted, or removed between minor versions) +2. Does the intercepted method still exist with a compatible signature? (parameters may be added/removed/reordered) +3. Do the witness classes still correctly distinguish versions? (a witness class that exists in both old and new versions won't prevent the plugin from loading on an incompatible version) +4. Do the runtime APIs called by the interceptor still exist? (e.g., calling `cluster.getDescription()` will crash if that method was removed, even if the plugin loaded successfully) + +**How to verify — clone the library source locally:** +```bash +# Clone specific version tag to /tmp for easy source code inspection +cd /tmp && git clone --depth 1 --branch {tag} https://github.com/{org}/{repo}.git {local-name} + +# Examples: +git clone --depth 1 --branch r4.9.0 https://github.com/mongodb/mongo-java-driver.git mongo-4.9 +git clone --depth 1 --branch v2.4.13.RELEASE https://github.com/spring-projects/spring-kafka.git spring-kafka-2.4 + +# Then grep/read the actual source files to check class/method existence +grep -rn "getFilter\|getWriteRequests" /tmp/mongo-4.9/driver-core/src/main/com/mongodb/internal/operation/ +``` + +This is faster and more reliable than fetching individual files via raw GitHub URLs. You can `grep`, `diff` between versions, and trace the full execution path. + +**Also check for import-time class loading failures:** +If a plugin helper class (not just the instrumentation class) imports a library class that was removed, the entire helper class will fail to load with `NoClassDefFoundError` at runtime. This silently breaks ALL functionality in that helper — not just the code paths using the removed class. Verify that every `import` statement in plugin support classes resolves to an existing class in the target version. + +**Real examples of why this matters:** +- MongoDB driver 4.9 removed `InsertOperation`, `DeleteOperation`, `UpdateOperation` — `MongoOperationHelper` imported all three, causing the entire class to fail loading with `NoClassDefFoundError`, silently losing ALL `db.bind_vars` tags even for operations that still exist (like `FindOperation`, `AggregateOperation`) +- MongoDB driver 4.11 removed `Cluster.getDescription()` — the plugin loads (witness classes pass) but crashes at runtime with `NoSuchMethodError` +- Feign 12.2 moved `ReflectiveFeign$BuildTemplateByResolvingArgs` to `RequestTemplateFactoryResolver$BuildTemplateByResolvingArgs` — the path variable interception silently stops working +- MariaDB 3.0 renamed every JDBC wrapper class (`MariaDbConnection` → `Connection`) — none of the plugin's `byName` matchers match anything + +**When extending `support-version.list` to add newer versions:** +Before adding a version, verify that every class and method the plugin intercepts still exists in that version's source. A plugin test passing does not mean everything works — it only means the test scenario's specific code path exercised the intercepted methods. Missing interception points may go undetected if the test doesn't cover them. + +## Step 2 - Create Plugin Module + +### Directory Structure + +**SDK plugin** (most common): +``` +apm-sniffer/apm-sdk-plugin/{framework}-{version}-plugin/ + pom.xml + src/main/java/org/apache/skywalking/apm/plugin/{framework}/v{N}/ + define/ + {Target}Instrumentation.java # One per target class + {Target}Interceptor.java # One per interception concern + {Target}ConstructorInterceptor.java # If intercepting constructors + {PluginName}PluginConfig.java # If plugin needs configuration + src/main/resources/ + skywalking-plugin.def # Plugin registration + src/test/java/org/apache/skywalking/apm/plugin/{framework}/v{N}/ + {Target}InterceptorTest.java # Unit tests +``` + +**Bootstrap plugin** (for JDK classes): +``` +apm-sniffer/bootstrap-plugins/{name}-plugin/ + (same structure, but instrumentation class overrides isBootstrapInstrumentation) +``` + +**Optional plugin**: +``` +apm-sniffer/optional-plugins/{name}-plugin/ + (same structure as SDK plugin) +``` + +### pom.xml Template + +```xml + + + 4.0.0 + + + org.apache.skywalking + apm-sdk-plugin + ${revision} + + + {framework}-{version}-plugin + jar + + + X.Y.Z + + + + + + com.example + target-library + ${target-library.version} + provided + + + +``` + +**CRITICAL dependency rules:** +- Target library: **always `provided` scope** (supplied by the application at runtime) +- `apm-agent-core`: inherited from parent POM as `provided` +- `apm-util`: inherited from parent POM as `provided` +- Never bundle target library classes into the plugin JAR +- If the plugin needs a 3rd-party utility not already in agent-core, discuss with maintainers first + +### Register in Parent POM + +Add the new module to the parent `pom.xml`: +```xml + + ... + {framework}-{version}-plugin + +``` + +## Step 3 - Implement Instrumentation Class (V2 API) + +**ALWAYS use V2 API for new plugins.** V1 is legacy. + +### Import Rules (Enforced by Checkstyle) + +Plugins may ONLY import from: +- `java.*` - Java standard library +- `org.apache.skywalking.*` - SkyWalking modules +- `net.bytebuddy.*` - ByteBuddy (for matchers in instrumentation classes) + +**No other 3rd-party imports are allowed in instrumentation/activation files.** This is enforced by `apm-checkstyle/importControl.xml`. Interceptor classes CAN reference target library classes (they're loaded after the target library). + +### Class Matching + +**CRITICAL: NEVER use `.class` references in instrumentation definitions.** Always use string literals. + +```java +// WRONG - breaks agent if class doesn't exist at runtime +byName(SomeThirdPartyClass.class.getName()) +takesArgument(0, SomeThirdPartyClass.class) + +// CORRECT - safe string literals +byName("com.example.SomeThirdPartyClass") +takesArgumentWithType(0, "com.example.SomeThirdPartyClass") +``` + +Available ClassMatch types (from `org.apache.skywalking.apm.agent.core.plugin.match`): + +| Matcher | Usage | Performance | +|---------|-------|-------------| +| `NameMatch.byName(String)` | Exact class name | Best (HashMap lookup) | +| `MultiClassNameMatch.byMultiClassMatch(String...)` | Multiple exact names | Good | +| `HierarchyMatch.byHierarchyMatch(String...)` | Implements interface / extends class | Expensive - avoid unless necessary | +| `ClassAnnotationMatch.byClassAnnotationMatch(String...)` | Has annotation(s) | Moderate | +| `MethodAnnotationMatch.byMethodAnnotationMatch(String...)` | Has method with annotation | Moderate | +| `PrefixMatch.nameStartsWith(String...)` | Class name prefix | Moderate | +| `RegexMatch.byRegexMatch(String...)` | Regex on class name | Expensive | +| `LogicalMatchOperation.and(match1, match2)` | AND composition | Depends on operands | +| `LogicalMatchOperation.or(match1, match2)` | OR composition | Depends on operands | + +**Prefer `NameMatch.byName()` whenever possible.** It uses a fast HashMap lookup. All other matchers require linear scanning. + +### Method Matching (ByteBuddy ElementMatcher API) + +Common matchers from `net.bytebuddy.matcher.ElementMatchers`: + +```java +// By name +named("methodName") + +// By argument count +takesArguments(2) +takesArguments(0) // no-arg methods + +// By argument type (use SkyWalking's helper - string-based, safe) +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +takesArgumentWithType(0, "com.example.SomeType") // arg at index 0 + +// By return type (SkyWalking helper) +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ReturnTypeNameMatch.returnsWithType; +returnsWithType("java.util.List") + +// By annotation (SkyWalking helper - string-based) +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.AnnotationTypeNameMatch.isAnnotatedWithType; +isAnnotatedWithType("org.springframework.web.bind.annotation.RequestMapping") + +// Visibility +isPublic() +isPrivate() + +// Composition +named("execute").and(takesArguments(1)) +named("method1").or(named("method2")) +not(isDeclaredBy(Object.class)) + +// Match any (use sparingly) +any() +``` + +### Instrumentation Template - Instance Methods + +```java +package org.apache.skywalking.apm.plugin.xxx.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.v2.InstanceMethodsInterceptV2Point; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +public class XxxInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 { + + private static final String ENHANCE_CLASS = "com.example.TargetClass"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.xxx.XxxInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; // null or empty array if not intercepting constructors + } + + @Override + public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() { + return new InstanceMethodsInterceptV2Point[] { + new InstanceMethodsInterceptV2Point() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("targetMethod"); + } + + @Override + public String getMethodsInterceptorV2() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} +``` + +### Instrumentation Template - Static Methods + +```java +import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassStaticMethodsEnhancePluginDefineV2; + +public class XxxStaticInstrumentation extends ClassStaticMethodsEnhancePluginDefineV2 { + @Override + public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() { + return new StaticMethodsInterceptPoint[] { + new StaticMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("factoryMethod").and(takesArguments(2)); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } +} +``` + +### Instrumentation Template - Both Instance + Static Methods + +Extend `ClassEnhancePluginDefineV2` and implement all four methods: +- `enhanceClass()` +- `getConstructorsInterceptPoints()` +- `getInstanceMethodsInterceptV2Points()` +- `getStaticMethodsInterceptPoints()` + +### Matching Interface/Abstract Class Implementations + +Use `HierarchyMatch` when you need to intercept all implementations of an interface: + +```java +import org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch; + +@Override +protected ClassMatch enhanceClass() { + return HierarchyMatch.byHierarchyMatch("com.example.SomeInterface"); +} +``` + +**When to use HierarchyMatch:** +- The library has an interface/abstract class with multiple implementations +- You cannot enumerate all implementation class names +- Example: intercepting all `javax.servlet.Servlet` implementations + +**Performance warning:** HierarchyMatch checks every loaded class against the hierarchy. Prefer `NameMatch` or `MultiClassNameMatch` if you know the concrete class names. + +**Combining with other matchers:** +```java +import org.apache.skywalking.apm.agent.core.plugin.match.logical.LogicalMatchOperation; + +@Override +protected ClassMatch enhanceClass() { + return LogicalMatchOperation.and( + PrefixMatch.nameStartsWith("com.example"), + HierarchyMatch.byHierarchyMatch("java.lang.Runnable") + ); +} +``` + +### Witness Classes for Version Detection + +Override `witnessClasses()` or `witnessMethods()` to activate the plugin only for specific library versions: + +```java +@Override +protected String[] witnessClasses() { + // Plugin only loads if this class exists in the application + return new String[] {"com.example.VersionSpecificClass"}; +} + +@Override +protected List witnessMethods() { + return Collections.singletonList( + new WitnessMethod("com.example.SomeClass", ElementMatchers.named("methodAddedInV2")) + ); +} +``` + +### Bootstrap Plugin Override + +For bootstrap plugins (instrumenting JDK classes), add: +```java +@Override +public boolean isBootstrapInstrumentation() { + return true; +} +``` + +**Bootstrap plugin rules:** +- Only for JDK core classes (java.*, javax.*, sun.*) +- Minimal interception scope (performance-critical paths) +- Extra care with class loading (bootstrap classloader visibility) +- Test with `runningMode: with_bootstrap` + +## Step 4 - Implement Interceptor Class (V2 API) + +### Available Interceptor Interfaces + +| Interface | Use Case | +|-----------|----------| +| `InstanceMethodsAroundInterceptorV2` | Instance method interception | +| `StaticMethodsAroundInterceptorV2` | Static method interception | +| `InstanceConstructorInterceptor` | Constructor interception (shared V1/V2) | + +### Core APIs Available in Interceptors + +**ContextManager** - Central tracing API (ThreadLocal-based): + +**CRITICAL threading rule:** All span lifecycle APIs (`createEntrySpan`, `createExitSpan`, `createLocalSpan`, `activeSpan`, `stopSpan`) operate on a **per-thread context via ThreadLocal**. By default, `createXxxSpan` and `stopSpan` MUST be called in the **same thread**. There are only two ways to work across threads: +1. **`ContextSnapshot` (capture/continued)** — snapshot the context in thread A, then `continued()` in thread B to link a NEW span in thread B back to the parent trace. Each thread manages its own span lifecycle independently. +2. **Async mode (`prepareForAsync`/`asyncFinish`)** — keeps a single span alive beyond the creating thread. Call `prepareForAsync()` in the original thread (before `stopSpan`), then `asyncFinish()` from any thread when the async work completes. Between `prepareForAsync` and `asyncFinish`, you may call tag/log/error on the span from any thread, but you must NOT call `ContextManager.stopSpan()` for that span again. + +```java +import org.apache.skywalking.apm.agent.core.context.ContextManager; + +// Create spans (must stopSpan in the SAME thread, unless async mode) +AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier); +AbstractSpan span = ContextManager.createLocalSpan(operationName); +AbstractSpan span = ContextManager.createExitSpan(operationName, contextCarrier, remotePeer); +AbstractSpan span = ContextManager.createExitSpan(operationName, remotePeer); + +// Span lifecycle (same thread as create, unless async mode) +ContextManager.activeSpan(); // Get current span in THIS thread +ContextManager.stopSpan(); // Stop current span in THIS thread +ContextManager.isActive(); // Check if context exists in THIS thread + +// Cross-process propagation (inject/extract ContextCarrier into headers/metadata) +ContextManager.inject(carrier); // Inject into outgoing carrier +ContextManager.extract(carrier); // Extract from incoming carrier + +// Cross-thread propagation (ContextSnapshot — link spans across threads) +ContextManager.capture(); // Capture snapshot in originating thread +ContextManager.continued(snapshot); // Continue from snapshot in receiving thread + +// Trace metadata +ContextManager.getGlobalTraceId(); +ContextManager.getSegmentId(); +ContextManager.getSpanId(); +``` + +**AbstractSpan** - Span configuration: +```java +span.setComponent(ComponentsDefine.YOUR_COMPONENT); // Required for Entry/Exit +span.setLayer(SpanLayer.HTTP); // Required for Entry/Exit +span.setOperationName("GET:/api/users"); +span.setPeer("host:port"); // Required for Exit spans + +// Tags +span.tag(Tags.URL, url); +span.tag(Tags.HTTP_RESPONSE_STATUS_CODE, statusCode); +span.tag(Tags.DB_TYPE, "sql"); +span.tag(Tags.DB_STATEMENT, sql); +span.tag(Tags.ofKey("custom.key"), value); + +// Error handling +span.errorOccurred(); +span.log(throwable); + +// Async support +span.prepareForAsync(); // Must call in original thread +span.asyncFinish(); // Call in async thread when done +``` + +**SpanLayer** values: `DB`, `RPC_FRAMEWORK`, `HTTP`, `MQ`, `CACHE`, `GEN_AI` + +**Standard Tags** (from `org.apache.skywalking.apm.agent.core.context.tag.Tags`): + +| Tag | Constant | Purpose | +|---------------------|----------------------------------|--------------------------| +| `url` | `Tags.URL` | Request URL | +| `http.status_code` | `Tags.HTTP_RESPONSE_STATUS_CODE` | HTTP status (IntegerTag) | +| `http.method` | `Tags.HTTP.METHOD` | HTTP method | +| `db.type` | `Tags.DB_TYPE` | Database type | +| `db.instance` | `Tags.DB_INSTANCE` | Database name | +| `db.statement` | `Tags.DB_STATEMENT` | SQL/query | +| `db.bind_variables` | `Tags.DB_BIND_VARIABLES` | Bound params | +| `mq.queue` | `Tags.MQ_QUEUE` | Queue name | +| `mq.topic` | `Tags.MQ_TOPIC` | Topic name | +| `mq.broker` | `Tags.MQ_BROKER` | Broker address | +| `cache.type` | `Tags.CACHE_TYPE` | Cache type | +| `cache.op` | `Tags.CACHE_OP` | "read" or "write" | +| `cache.cmd` | `Tags.CACHE_CMD` | Cache command | +| `cache.key` | `Tags.CACHE_KEY` | Cache key | +| Custom | `Tags.ofKey("key")` | Any custom tag | + +**EnhancedInstance** - Dynamic field for cross-interceptor data: +```java +// Store data (e.g., in constructor interceptor) +objInst.setSkyWalkingDynamicField(connectionInfo); + +// Retrieve data (e.g., in method interceptor) +ConnectionInfo info = (ConnectionInfo) objInst.getSkyWalkingDynamicField(); +``` + +**Logging** - Agent-internal logging (NOT application logging): +```java +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; + +private static final ILog LOGGER = LogManager.getLogger(MyInterceptor.class); +LOGGER.info("message: {}", value); +LOGGER.error("error", throwable); +``` + +**MeterFactory** - For meter plugins: +```java +import org.apache.skywalking.apm.toolkit.meter.MeterFactory; +import org.apache.skywalking.apm.toolkit.meter.Counter; +import org.apache.skywalking.apm.toolkit.meter.Gauge; +import org.apache.skywalking.apm.toolkit.meter.Histogram; + +Counter counter = MeterFactory.counter("metric_name") + .tag("key", "value") + .mode(Counter.Mode.INCREMENT) + .build(); +counter.increment(1.0); + +Gauge gauge = MeterFactory.gauge("metric_name", () -> pool.getActiveCount()) + .tag("pool_name", name) + .build(); + +Histogram histogram = MeterFactory.histogram("metric_name") + .steps(Arrays.asList(10.0, 50.0, 100.0, 500.0)) + .minValue(0) + .build(); +histogram.addValue(latencyMs); +``` + +### Interceptor Template - ExitSpan (Client/Producer) + +```java +package org.apache.skywalking.apm.plugin.xxx; + +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; + +public class XxxClientInterceptor implements InstanceMethodsAroundInterceptorV2 { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInvocationContext context) throws Throwable { + // 1. Build peer address from stored connection info + String remotePeer = (String) objInst.getSkyWalkingDynamicField(); + + // 2. Create ExitSpan with ContextCarrier for cross-process propagation + ContextCarrier contextCarrier = new ContextCarrier(); + AbstractSpan span = ContextManager.createExitSpan("operation/name", contextCarrier, remotePeer); + span.setComponent(ComponentsDefine.YOUR_COMPONENT); + SpanLayer.asHttp(span); // or asDB, asMQ, asRPCFramework, asCache + + // 3. Inject trace context into outgoing request headers + // The request object is typically one of the method arguments + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + // Set header on the outgoing request: + // request.setHeader(next.getHeadKey(), next.getHeadValue()); + } + + // 4. Set tags + Tags.URL.set(span, url); + + // 5. Store span in context for afterMethod + context.setContext(span); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret, MethodInvocationContext context) throws Throwable { + // Check response status, set tags/errors + AbstractSpan span = (AbstractSpan) context.getContext(); + // Example: Tags.HTTP_RESPONSE_STATUS_CODE.set(span, statusCode); + // if (statusCode >= 400) span.errorOccurred(); + + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { + ContextManager.activeSpan().log(t); + ContextManager.activeSpan().errorOccurred(); + } +} +``` + +### Interceptor Template - EntrySpan (Server/Consumer) + +```java +public class XxxServerInterceptor implements InstanceMethodsAroundInterceptorV2 { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInvocationContext context) throws Throwable { + // 1. Extract trace context from incoming request headers + ContextCarrier contextCarrier = new ContextCarrier(); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + // Read header from incoming request: + // next.setHeadValue(request.getHeader(next.getHeadKey())); + } + + // 2. Create EntrySpan (extracts context automatically) + AbstractSpan span = ContextManager.createEntrySpan("operation/name", contextCarrier); + span.setComponent(ComponentsDefine.YOUR_COMPONENT); + SpanLayer.asHttp(span); // or asMQ, asRPCFramework + span.setPeer(clientAddress); // Optional: client address + + context.setContext(span); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret, MethodInvocationContext context) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t, MethodInvocationContext context) { + ContextManager.activeSpan().log(t); + ContextManager.activeSpan().errorOccurred(); + } +} +``` + +### Interceptor Template - Constructor (Store Connection Info) + +```java +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +public class XxxConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + // Store connection info for later use by method interceptors + String host = (String) allArguments[0]; + int port = (int) allArguments[1]; + objInst.setSkyWalkingDynamicField(host + ":" + port); + } +} +``` + +### Cross-Thread Context Propagation (ContextSnapshot) + +Use `ContextSnapshot` when the library dispatches work to another thread and you want the new thread's spans to be linked to the parent trace. Each thread creates and stops its OWN spans — the snapshot only provides the link. + +```java +// Thread A (originating thread) — create span, capture snapshot, stop span (all same thread) +@Override +public void beforeMethod(..., MethodInvocationContext context) { + AbstractSpan span = ContextManager.createLocalSpan("async/dispatch"); + // Capture context snapshot BEFORE handing off to another thread + ContextSnapshot snapshot = ContextManager.capture(); + // Store snapshot on the task object via EnhancedInstance dynamic field + ((EnhancedInstance) allArguments[0]).setSkyWalkingDynamicField(snapshot); + ContextManager.stopSpan(); // Stop span in THIS thread (same thread as create) +} + +// Thread B (receiving thread) — create its OWN span, link to parent via continued() +@Override +public void beforeMethod(EnhancedInstance objInst, ...) { + ContextSnapshot snapshot = (ContextSnapshot) objInst.getSkyWalkingDynamicField(); + if (snapshot != null) { + AbstractSpan span = ContextManager.createLocalSpan("async/execute"); + ContextManager.continued(snapshot); // Link this span to the parent trace + } +} + +@Override +public Object afterMethod(...) { + if (ContextManager.isActive()) { + ContextManager.stopSpan(); // Stop span in THIS thread (same thread as create) + } + return ret; +} +``` + +### Async Span Pattern (prepareForAsync / asyncFinish) + +Use this when a **single span** needs to stay open across thread boundaries — e.g., an ExitSpan created before an async call, finished when the callback fires in another thread. The key difference from ContextSnapshot: here one span lives across threads instead of each thread having its own span. + +```java +// Thread A — create span, mark async, stop context (all same thread) +@Override +public void beforeMethod(..., MethodInvocationContext context) { + AbstractSpan span = ContextManager.createExitSpan("async/call", remotePeer); + span.setComponent(ComponentsDefine.YOUR_COMPONENT); + SpanLayer.asHttp(span); + + span.prepareForAsync(); // Mark: this span will finish in another thread + ContextManager.stopSpan(); // Detach from THIS thread's context (required, same thread as create) + + // Store span reference on the callback object's dynamic field + ((EnhancedInstance) callback).setSkyWalkingDynamicField(span); +} + +// Thread B (callback/completion handler) — finish the async span +@Override +public void beforeMethod(EnhancedInstance objInst, ...) { + AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField(); + if (span != null) { + // Add response info to the span (tag/log/error are thread-safe after prepareForAsync) + span.tag(Tags.HTTP_RESPONSE_STATUS_CODE, statusCode); + if (isError) span.errorOccurred(); + span.asyncFinish(); // Must match prepareForAsync count + } +} +``` + +### Plugin Configuration (Optional) + +```java +import org.apache.skywalking.apm.agent.core.boot.PluginConfig; + +public class XxxPluginConfig { + public static class Plugin { + @PluginConfig(root = XxxPluginConfig.class) + public static class Xxx { + // Config key: plugin.xxx.trace_param + public static boolean TRACE_PARAM = false; + // Config key: plugin.xxx.max_length + public static int MAX_LENGTH = 256; + } + } +} +``` + +## Step 5 - Register Plugin + +Create `src/main/resources/skywalking-plugin.def`: +``` +plugin-name=org.apache.skywalking.apm.plugin.xxx.define.XxxInstrumentation +plugin-name=org.apache.skywalking.apm.plugin.xxx.define.XxxOtherInstrumentation +``` + +Format: `{plugin-id}={fully.qualified.InstrumentationClassName}` (one line per instrumentation class, all sharing the same plugin-id prefix). + +## Step 6 - Write Unit Tests + +### Test Setup Pattern + +```java +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; + +@RunWith(TracingSegmentRunner.class) +public class XxxInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule agentServiceRule = new AgentServiceRule(); + + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + @Mock + private EnhancedInstance enhancedInstance; + + private XxxInterceptor interceptor; + + @Before + public void setUp() { + interceptor = new XxxInterceptor(); + // Setup mocks + } + + @Test + public void testNormalRequest() throws Throwable { + // Arrange + Object[] allArguments = new Object[] { /* mock args */ }; + Class[] argumentsTypes = new Class[] { /* arg types */ }; + + // Act + interceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsTypes, null); + interceptor.afterMethod(enhancedInstance, null, allArguments, argumentsTypes, mockResponse, null); + + // Assert spans + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment segment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(segment); + assertThat(spans.size(), is(1)); + // Verify span properties... + } +} +``` + +## Step 7 - Write E2E Plugin Tests + +### Test Scenario Structure + +``` +test/plugin/scenarios/{framework}-{version}-scenario/ + bin/startup.sh + config/expectedData.yaml + src/main/java/org/apache/skywalking/apm/testcase/{framework}/ + controller/CaseController.java # HTTP endpoints + pom.xml + configuration.yml + support-version.list +``` + +**When copying an existing scenario to create a new one**, update the scenario name in ALL of these files: +- `pom.xml` — `artifactId`, `name`, `finalName` +- `src/main/assembly/assembly.xml` — JAR filename reference +- `bin/startup.sh` — JAR filename in java -jar command +- `config/expectedData.yaml` — `serviceName` field AND `parentService` in refs (but NOT URL paths — those are the app context path) +- `support-version.list` — new versions +- For JDK 17+ scenarios: update `compiler.version` to `17`, `spring.boot.version` to `3.x`, change `javax.annotation` imports to `jakarta.annotation` in Java source +- Add the scenario to the appropriate CI workflow (`plugins-test.*.yaml` for JDK 8, `plugins-jdk17-test.*.yaml` for JDK 17) + +### configuration.yml + +```yaml +type: jvm +entryService: http://localhost:8080/{scenario-name}/case/{endpoint} +healthCheck: http://localhost:8080/{scenario-name}/case/healthCheck +startScript: ./bin/startup.sh +environment: [] +dependencies: {} +``` + +### expectedData.yaml for Tracing + +```yaml +segmentItems: + - serviceName: {scenario-name} + segmentSize: ge 1 + segments: + - segmentId: not null + spans: + - operationName: your/operation + parentSpanId: -1 + spanId: 0 + spanLayer: Http # Http, DB, RPCFramework, MQ, CACHE + spanType: Exit # Entry, Exit, Local + startTime: nq 0 + endTime: nq 0 + componentId: 2 # Must match ComponentsDefine ID + isError: false + peer: 'host:port' + skipAnalysis: 'false' + tags: + - {key: url, value: not null} + - {key: http.method, value: GET} + logs: [] + refs: [] +``` + +### expectedData.yaml for Meters + +```yaml +meterItems: + - serviceName: {scenario-name} + meterSize: ge 1 + meters: + - meterId: + name: your_counter_name + tags: + - {name: tag_key, value: tag_value} + singleValue: gt 0 +``` + +### Assertion Operators + +| Operator | Meaning | +|----------|---------| +| `eq VALUE` | Equals | +| `nq VALUE` | Not equals | +| `ge VALUE` | Greater or equal | +| `gt VALUE` | Greater than | +| `not null` | Must be present | +| `null` | Must be absent | + +### Running Tests + +```bash +bash ./test/plugin/run.sh -f {scenario-name} +bash ./test/plugin/run.sh --debug {scenario-name} # Save actualData.yaml for debugging +``` + +**IMPORTANT: Run E2E test scenarios ONE AT A TIME.** Multiple scenarios use the same Docker ports (8080, etc.) and will conflict if run in parallel. Always wait for one scenario to finish before starting the next. + +## Step 8 - Shading (Package Relocation) + +Plugins automatically inherit ByteBuddy shading from the parent POM: +```xml + + net.bytebuddy + org.apache.skywalking.apm.dependencies.net.bytebuddy + +``` + +The agent-core module handles shading of all core dependencies: +- `com.google.*` -> `org.apache.skywalking.apm.dependencies.com.google.*` +- `io.grpc.*` -> `org.apache.skywalking.apm.dependencies.io.grpc.*` +- `io.netty.*` -> `org.apache.skywalking.apm.dependencies.io.netty.*` +- `org.slf4j.*` -> `org.apache.skywalking.apm.dependencies.org.slf4j.*` + +**Plugins should NOT add their own shade configurations** unless they need to bundle a library not in agent-core (rare, requires maintainer approval). If a plugin needs a reporter-level dependency, see `optional-reporter-plugins/kafka-reporter-plugin/pom.xml` for the pattern. + +## Step 9 - Code Style Checklist + +Before submitting: +- [ ] No `System.out.println` (use `ILog` from `LogManager`) +- [ ] No `@author` tags (ASF policy) +- [ ] No Chinese characters in source +- [ ] No tab characters (use 4 spaces) +- [ ] No star imports (`import xxx.*`) +- [ ] No unused imports +- [ ] `@Override` on all overridden methods +- [ ] Apache 2.0 license header on all source files +- [ ] File length under 3000 lines +- [ ] Constants in `UPPER_SNAKE_CASE` +- [ ] Types in `PascalCase`, variables in `camelCase` +- [ ] Imports only from `java.*`, `org.apache.skywalking.*`, `net.bytebuddy.*` (in instrumentation files) +- [ ] Target library dependencies in `provided` scope +- [ ] Using V2 API for new plugins +- [ ] String literals (not `.class` references) in instrumentation definitions +- [ ] `skywalking-plugin.def` registered +- [ ] Module added to parent POM + +## Step 10 - Update Documentation + +After verifying the plugin works (locally or via CI), update these documentation files: + +**1. `docs/en/setup/service-agent/java-agent/Supported-list.md`** +Update the version range for the relevant entry. Format example: +``` + * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14, 3.4.0-3.12.7, 4.0.0-4.10.2 +``` +For new plugins, add a new bullet under the appropriate category. + +**2. `CHANGES.md`** +Add a changelog entry under the current unreleased version section. Format: +``` +* Extend {plugin-name} plugin to support {library} {version-range}. +``` +Or for new plugins: +``` +* Add {framework} {version} plugin. +``` + +**3. `test/plugin/scenarios/{scenario}/support-version.list`** +Add verified versions. Only include the **latest patch version for each minor version** — do not list every patch release. + +The version list supports **extra Maven properties** per version line using comma-separated `key=value` pairs: +``` +# Simple version (default pom properties) +2.3.10.RELEASE + +# Version with overridden Maven properties +2.7.14,spring.boot.version=2.5.15 +2.8.11,spring.boot.version=2.7.18 +3.1.4,spring.boot.version=3.2.12 +``` + +This is useful when different framework versions need different dependency versions (e.g., spring-kafka minor versions require matching Spring Boot versions). The extra properties are passed as `-D` flags to Maven during the scenario build. + +**IMPORTANT:** Maven `-D` overrides work for `` and direct `${prop}` references, but do NOT override BOM versions resolved via `` imports. If a BOM version needs to change, set the default in the pom to the highest needed version, not the lowest. + +**Spring Boot / Spring Kafka compatibility mapping** (for reference): +- spring-kafka 2.3-2.6 → Spring Boot 2.3 (default) +- spring-kafka 2.7 → Spring Boot 2.5 (2.6+ autoconfigure requires `CommonErrorHandler` from spring-kafka 2.8) +- spring-kafka 2.8-2.9 → Spring Boot 2.7 +- spring-kafka 3.0 → Spring Boot 3.0 +- spring-kafka 3.1-3.3 → Spring Boot 3.2 (requires Spring Framework 6.1) + +**This step is mandatory.** Documentation updates are part of the PR requirements. + +## Quick Reference - Plugin Type Decision Tree + +``` +Is the target a JDK core class (java.*, sun.*)? + YES -> Bootstrap plugin (isBootstrapInstrumentation = true) + NO -> Is it commonly used and should be auto-activated? + YES -> SDK plugin (apm-sdk-plugin/) + NO -> Optional plugin (optional-plugins/) + +What span type? + Receiving requests (HTTP server, MQ consumer, RPC provider) -> EntrySpan + Making outgoing calls (HTTP client, DB, cache, MQ producer) -> ExitSpan + Internal processing (annotation, local logic) -> LocalSpan + +Need cross-process propagation? + YES -> Use ContextCarrier (inject on exit, extract on entry) + NO -> No carrier needed + +Need cross-thread propagation? + YES -> Use ContextSnapshot (capture + continued) OR prepareForAsync/asyncFinish + NO -> Standard span lifecycle + +Need metrics without traces? + YES -> Meter plugin (Counter/Gauge/Histogram via MeterFactory) + +Need both traces and metrics? + YES -> Separate interceptors or combine in same interceptor +``` \ No newline at end of file diff --git a/.github/workflows/plugins-jdk17-test.0.yaml b/.github/workflows/plugins-jdk17-test.0.yaml index 74ae79f0fe..49b3675c01 100644 --- a/.github/workflows/plugins-jdk17-test.0.yaml +++ b/.github/workflows/plugins-jdk17-test.0.yaml @@ -81,6 +81,9 @@ jobs: - jetty-10.x-scenario - spring-ai-1.x-scenario - spring-rabbitmq-scenario + - graphql-20plus-scenario + - spring-kafka-3.x-scenario + - undertow-2.3.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index 3d5880fd9f..36ad8289a0 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -69,6 +69,7 @@ jobs: case: - aerospike-scenario - mysql-scenario + - mysql-9.x-scenario - undertow-scenario - webflux-scenario - zookeeper-scenario diff --git a/CHANGES.md b/CHANGES.md index e49c314aab..f55806ecda 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,14 @@ Release Notes. * Add Spring AI 1.x plugin and GenAI layer. * Fix httpclient-5.x plugin injecting sw8 propagation headers into ClickHouse HTTP requests (port 8123), causing HTTP 400. Add `PROPAGATION_EXCLUDE_PORTS` config to skip tracing (including header injection) for specified ports in the classic client interceptor. * Add Spring RabbitMQ 2.x - 4.x plugin. +* Extend MySQL plugin to support MySQL Connector/J 8.4.0 and 9.x (9.0 -> 9.6). +* Extend MariaDB plugin to support MariaDB Connector/J 2.7.x. +* Extend MongoDB 4.x plugin to support MongoDB Java Driver 4.2 -> 4.10. Fix db.bind_vars extraction for driver 4.9+ where InsertOperation/DeleteOperation/UpdateOperation classes were removed. +* Extend Feign plugin to support OpenFeign 10.x, 11.x, 12.1. +* Extend Undertow plugin to support Undertow 2.1.x, 2.2.x, 2.3.x. +* Extend GraphQL plugin to support graphql-java 18 -> 24 (20+ requires JDK 17). +* Extend Spring Kafka plugin to support Spring Kafka 2.4 -> 2.9 and 3.0 -> 3.3. +* Enhance test/plugin/run.sh to support extra Maven properties per version in support-version.list (format: version,key=value). All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/CLAUDE.md b/apm-sniffer/apm-sdk-plugin/CLAUDE.md index a0c73a2a04..eb88c1cbe1 100644 --- a/apm-sniffer/apm-sdk-plugin/CLAUDE.md +++ b/apm-sniffer/apm-sdk-plugin/CLAUDE.md @@ -292,6 +292,10 @@ dependencies: # External services (docker-compose 4.3.6 4.4.1 4.5.0 + +# Optional: extra Maven properties per version (comma-separated key=value) +# Useful when different versions need different dependency versions +2.7.14,spring.boot.version=2.5.15 ``` **expectedData.yaml:** diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/LegacyOperationHelper.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/LegacyOperationHelper.java new file mode 100644 index 0000000000..3c3a19a7b7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/LegacyOperationHelper.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.mongodb.v4.support; + +import com.mongodb.internal.bulk.DeleteRequest; +import com.mongodb.internal.bulk.InsertRequest; +import com.mongodb.internal.bulk.UpdateRequest; +import com.mongodb.internal.operation.DeleteOperation; +import com.mongodb.internal.operation.InsertOperation; +import com.mongodb.internal.operation.UpdateOperation; + +import java.util.List; + +/** + * Handles trace parameter extraction for legacy MongoDB driver versions (4.0 - 4.8). + * InsertOperation, DeleteOperation, and UpdateOperation were removed in driver 4.9. + * This class is only loaded when those classes exist (guarded by + * {@link MongoOperationHelper#HAS_LEGACY_WRITE_OPERATIONS}). + */ +@SuppressWarnings("deprecation") +class LegacyOperationHelper { + + private LegacyOperationHelper() { + } + + /** + * Extract trace parameters from legacy write operation types. + * @return the trace parameter string, or null if obj is not a legacy write operation + */ + static String getTraceParam(Object obj) { + if (obj instanceof DeleteOperation) { + List writeRequestList = ((DeleteOperation) obj).getDeleteRequests(); + return MongoOperationHelper.getFilter(writeRequestList); + } else if (obj instanceof InsertOperation) { + List writeRequestList = ((InsertOperation) obj).getInsertRequests(); + return MongoOperationHelper.getFilter(writeRequestList); + } else if (obj instanceof UpdateOperation) { + List writeRequestList = ((UpdateOperation) obj).getUpdateRequests(); + return MongoOperationHelper.getFilter(writeRequestList); + } + return null; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoOperationHelper.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoOperationHelper.java index 8a561cc887..96cf84c985 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoOperationHelper.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoOperationHelper.java @@ -27,18 +27,15 @@ import com.mongodb.internal.operation.CreateCollectionOperation; import com.mongodb.internal.operation.CreateIndexesOperation; import com.mongodb.internal.operation.CreateViewOperation; -import com.mongodb.internal.operation.DeleteOperation; import com.mongodb.internal.operation.DistinctOperation; import com.mongodb.internal.operation.FindAndDeleteOperation; import com.mongodb.internal.operation.FindAndReplaceOperation; import com.mongodb.internal.operation.FindAndUpdateOperation; import com.mongodb.internal.operation.FindOperation; -import com.mongodb.internal.operation.InsertOperation; import com.mongodb.internal.operation.ListCollectionsOperation; import com.mongodb.internal.operation.MapReduceToCollectionOperation; import com.mongodb.internal.operation.MapReduceWithInlineResultsOperation; import com.mongodb.internal.operation.MixedBulkWriteOperation; -import com.mongodb.internal.operation.UpdateOperation; import org.bson.BsonDocument; import java.util.List; @@ -49,6 +46,21 @@ }) public class MongoOperationHelper { + // InsertOperation, DeleteOperation, UpdateOperation were removed in MongoDB driver 4.9. + // Use class existence check to determine which extraction path to use. + private static final boolean HAS_LEGACY_WRITE_OPERATIONS; + + static { + boolean hasLegacy; + try { + Class.forName("com.mongodb.internal.operation.InsertOperation"); + hasLegacy = true; + } catch (ClassNotFoundException e) { + hasLegacy = false; + } + HAS_LEGACY_WRITE_OPERATIONS = hasLegacy; + } + private MongoOperationHelper() { } @@ -69,22 +81,25 @@ public static String getTraceParam(Object obj) { } else if (obj instanceof FindOperation) { BsonDocument filter = ((FindOperation) obj).getFilter(); return limitFilter(filter.toString()); - } else if (obj instanceof ListCollectionsOperation) { + } else if (obj instanceof ListCollectionsOperation) { BsonDocument filter = ((ListCollectionsOperation) obj).getFilter(); return limitFilter(filter.toString()); } else if (obj instanceof MapReduceWithInlineResultsOperation) { BsonDocument filter = ((MapReduceWithInlineResultsOperation) obj).getFilter(); return limitFilter(filter.toString()); - } else if (obj instanceof DeleteOperation) { - List writeRequestList = ((DeleteOperation) obj).getDeleteRequests(); - return getFilter(writeRequestList); - } else if (obj instanceof InsertOperation) { - List writeRequestList = ((InsertOperation) obj).getInsertRequests(); - return getFilter(writeRequestList); - } else if (obj instanceof UpdateOperation) { - List writeRequestList = ((UpdateOperation) obj).getUpdateRequests(); - return getFilter(writeRequestList); - } else if (obj instanceof CreateCollectionOperation) { + } else if (HAS_LEGACY_WRITE_OPERATIONS) { + String result = LegacyOperationHelper.getTraceParam(obj); + if (result != null) { + return result; + } + return getCommonTraceParam(obj); + } else { + return getCommonTraceParam(obj); + } + } + + private static String getCommonTraceParam(Object obj) { + if (obj instanceof CreateCollectionOperation) { String filter = ((CreateCollectionOperation) obj).getCollectionName(); return limitFilter(filter); } else if (obj instanceof CreateIndexesOperation) { @@ -128,7 +143,7 @@ private static String getPipelines(List pipelines) { return params.toString(); } - private static String getFilter(List writeRequestList) { + static String getFilter(List writeRequestList) { StringBuilder params = new StringBuilder(); for (WriteRequest request : writeRequestList) { if (request instanceof InsertRequest) { diff --git a/docs/en/setup/service-agent/java-agent/Claude-Skills.md b/docs/en/setup/service-agent/java-agent/Claude-Skills.md new file mode 100644 index 0000000000..f851ee6c52 --- /dev/null +++ b/docs/en/setup/service-agent/java-agent/Claude-Skills.md @@ -0,0 +1,64 @@ +# Claude Code Skills + +[Claude Code](https://claude.ai/claude-code) is an AI-powered CLI tool by Anthropic. This project includes +custom **skills** (`.claude/skills/`) that teach Claude Code how to work with the SkyWalking Java Agent codebase. + +Skills are reusable prompt templates that Claude Code can invoke via slash commands. They encode project-specific +knowledge so that common development tasks can be performed consistently and correctly. + +## Available Skills + +### `/new-plugin` — Develop a New Plugin + +Guides the full lifecycle of creating a new SkyWalking Java agent plugin: + +1. **Gather requirements** — target library, observation type (tracing/meter), span types +2. **Identify interception points** — understand library usage, trace execution flow, choose classes/methods +3. **Create plugin module** — directory structure, pom.xml, dependencies (`provided` scope) +4. **Implement instrumentation** — V2 API, class matching (ByteBuddy), method matching +5. **Implement interceptors** — ContextManager spans, ContextCarrier inject/extract, EnhancedInstance dynamic fields +6. **Register plugin** — `skywalking-plugin.def` +7. **Write unit tests** — TracingSegmentRunner, SegmentStorage +8. **Write E2E tests** — Docker-based scenarios, expectedData.yaml +9. **Code style** — checkstyle compliance, import restrictions +10. **Update documentation** — Supported-list.md, CHANGES.md + +Key principles encoded in this skill: +- Always use **V2 API** (`ClassEnhancePluginDefineV2`, `InstanceMethodsAroundInterceptorV2`) +- **Never use `.class` references** in instrumentation — always string literals +- **Never use reflection** to access private fields — choose interception points with accessible data +- **Never use Maps** to cache per-instance context — use `EnhancedInstance.setSkyWalkingDynamicField()` +- **Verify actual source code** of target libraries — never speculate from version numbers +- Span lifecycle APIs are **ThreadLocal-based** — create/stop in same thread unless async mode + +### `/compile` — Build the Project + +Runs the appropriate build command based on what you need: +- Full build with or without tests +- Single module build +- Checkstyle check +- Plugin E2E test scenarios +- Protobuf source generation for IDE setup + +## How to Use + +1. Install [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) +2. Navigate to the `skywalking-java` repository root +3. Run `claude` to start Claude Code +4. Type `/new-plugin` or `/compile` to invoke a skill + +Skills can also be triggered implicitly — when you describe a task that matches a skill's purpose, +Claude Code may suggest or invoke it automatically. + +## Project Context Files + +In addition to skills, the project includes `CLAUDE.md` files that provide codebase context: + +| File | Purpose | +|------|---------| +| `CLAUDE.md` (root) | Project overview, build system, architecture, conventions | +| `apm-sniffer/apm-sdk-plugin/CLAUDE.md` | SDK plugin development guide (V2 API, class matching, testing) | +| `apm-sniffer/bootstrap-plugins/CLAUDE.md` | Bootstrap plugin specifics (JDK class instrumentation) | + +These files are automatically loaded by Claude Code when working in the repository, providing it with +the knowledge needed to assist with development tasks. diff --git a/docs/en/setup/service-agent/java-agent/Plugin-test.md b/docs/en/setup/service-agent/java-agent/Plugin-test.md index e9dabb7515..a40eb82e35 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-test.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-test.md @@ -101,6 +101,16 @@ File Name | Descriptions `*` support-version.list format requires every line for a single version (contains only the last version number of each minor version). You may use `#` to comment out this version. +Each version line supports optional extra Maven properties using comma-separated `key=value` pairs: +``` +# Simple version +2.3.10.RELEASE + +# Version with extra Maven properties (passed as -D flags) +2.7.14,spring.boot.version=2.5.15 +``` +This allows different framework versions to use different dependency versions without creating separate test scenarios. + ### configuration.yml | Field | description diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 1645c43b4e..bbc7da6940 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -16,7 +16,7 @@ metrics based on the tracing data. * Resin 4 (Optional¹), See [SkySPM Plugin Repository](https://github.com/SkyAPM/java-plugin-extensions) * [Jetty Server](http://www.eclipse.org/jetty/) 9.x -> 11.x * [Spring WebFlux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) 5.x (Optional²) -> 6.x (Optional²) - * [Undertow](http://undertow.io/) 1.3.0.Final -> 2.0.27.Final + * [Undertow](http://undertow.io/) 1.3.0.Final -> 2.3.18.Final * [RESTEasy](https://resteasy.dev/) 3.1.0.Final -> 6.2.4.Final * [Play Framework](https://www.playframework.com/) 2.6.x -> 2.8.x * [Light4J Microservices Framework](https://doc.networknt.com/) 1.6.x -> 2.x @@ -28,7 +28,7 @@ metrics based on the tracing data. * [Netty HTTP](https://github.com/netty/netty) 4.1.x (Optional²) * [Solon](https://github.com/opensolon/solon) 2.7.x -> 2.8.x * HTTP Client - * [Feign](https://github.com/OpenFeign/feign) 9.x + * [Feign](https://github.com/OpenFeign/feign) 9.x -> 12.1 * [Netflix Spring Cloud Feign](https://github.com/spring-cloud/spring-cloud-openfeign) 1.1.x -> 2.x * [Okhttp](https://github.com/square/okhttp) 2.x -> 3.x -> 4.x * [Apache httpcomponent HttpClient](http://hc.apache.org/) 2.0 -> 3.1, 4.2, 4.3, 5.0, 5.1 @@ -45,12 +45,12 @@ metrics based on the tracing data. * [Spring Cloud Gateway](https://spring.io/projects/spring-cloud-gateway) 2.0.2.RELEASE -> 4.3.x (Optional²) * [Apache ShenYu](https://shenyu.apache.org) (Rich protocol support: `HTTP`,`Spring Cloud`,`gRPC`,`Dubbo`,`SOFARPC`,`Motan`,`Tars`) 2.4.x (Optional²) * JDBC - * Mysql Driver 5.x, 6.x, 8.x + * Mysql Driver 5.x, 6.x, 8.x, 9.x * Oracle Driver (Optional¹), See [SkySPM Plugin Repository](https://github.com/SkyAPM/java-plugin-extensions) * H2 Driver 1.3.x -> 1.4.x * [ShardingSphere](https://github.com/apache/shardingsphere) 3.0.0, 4.0.0, 4.0.1, 4.1.0, 4.1.1, 5.0.0 * PostgreSQL Driver 8.x, 9.x, 42.x - * Mariadb Driver 2.x, 1.8 + * Mariadb Driver 1.8, 2.x (2.0 -> 2.7) * [InfluxDB](https://github.com/influxdata/influxdb-java) 2.5 -> 2.17 * [Mssql-Jtds](https://github.com/milesibastos/jTDS) 1.x * [Mssql-jdbc](https://github.com/microsoft/mssql-jdbc) 6.x -> 8.x @@ -77,7 +77,7 @@ metrics based on the tracing data. * [RocketMQ](https://github.com/apache/rocketmq) 3.x-> 5.x * [RocketMQ-gRPC](http://github.com/apache/rocketmq-clients) 5.x * [Kafka](http://kafka.apache.org) 0.11.0.0 -> 3.9.1 - * [Spring-Kafka](https://github.com/spring-projects/spring-kafka) Spring Kafka Consumer 1.3.x -> 2.3.x (2.0.x and 2.1.x not tested and not recommended by [the official document](https://spring.io/projects/spring-kafka)) + * [Spring-Kafka](https://github.com/spring-projects/spring-kafka) Spring Kafka Consumer 1.3.x -> 3.3.x (2.0.x and 2.1.x not tested and not recommended by [the official document](https://spring.io/projects/spring-kafka)) * [ActiveMQ](https://github.com/apache/activemq) 5.10.0 -> 5.15.4 * [RabbitMQ](https://www.rabbitmq.com/) 3.x-> 5.x * [Spring-RabbitMQ](https://github.com/spring-projects/spring-amqp) 2.x -> 4.x @@ -91,7 +91,7 @@ metrics based on the tracing data. * [Jedis](https://github.com/xetorthio/jedis) 2.x-4.x * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 3.5.0 -> 3.30.0 * [Lettuce](https://github.com/lettuce-io/lettuce-core) 5.x -> 6.7.1 - * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14, 3.4.0-3.12.7, 4.0.0-4.1.0 + * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14, 3.4.0-3.12.7, 4.0.0-4.10.2 * Memcached Client * [Spymemcached](https://github.com/couchbase/spymemcached) 2.x * [Xmemcached](https://github.com/killme2008/xmemcached) 2.x @@ -147,7 +147,7 @@ metrics based on the tracing data. * Kotlin * [Coroutine](https://kotlinlang.org/docs/coroutines-overview.html) 1.0.1 -> 1.3.x (Optional²) * GraphQL - * [Graphql](https://github.com/graphql-java) 8.0 -> 17.x + * [Graphql](https://github.com/graphql-java) 8.0 -> 24.x * Pool * [Apache Commons DBCP](https://github.com/apache/commons-dbcp) 2.x * [Alibaba Druid](https://github.com/alibaba/druid) 1.x diff --git a/docs/menu.yml b/docs/menu.yml index 7ba331d586..edf1dfa77b 100644 --- a/docs/menu.yml +++ b/docs/menu.yml @@ -106,6 +106,8 @@ catalog: path: "/en/setup/service-agent/java-agent/java-plugin-development-guide/" - name: "Java Agent Performance Test" path: "https://skyapmtest.github.io/Agent-Benchmarks/" + - name: "Claude Code Skills" + path: "/en/setup/service-agent/java-agent/Claude-Skills" - name: "FAQs" catalog: - name: "Why is java.ext.dirs not supported?" diff --git a/test/plugin/run.sh b/test/plugin/run.sh index 164eebfe6d..b530c78e98 100755 --- a/test/plugin/run.sh +++ b/test/plugin/run.sh @@ -231,8 +231,21 @@ ls "${jacoco_home}"/jacocoagent.jar || curl -Lso "${jacoco_home}"/jacocoagent.ja ls "${jacoco_home}"/jacococli.jar || curl -Lso "${jacoco_home}"/jacococli.jar https://repo1.maven.org/maven2/org/jacoco/org.jacoco.cli/${jacoco_version}/org.jacoco.cli-${jacoco_version}-nodeps.jar supported_versions=`grep -v -E "^$|^#" ${supported_version_file}` -for version in ${supported_versions} +for version_line in ${supported_versions} do + # Support format: version[,key=value[,key=value...]] + # e.g., "2.7.14,spring.boot.version=2.7.19" + # First token is test.framework.version, rest are extra Maven properties. + version=$(echo "${version_line}" | cut -d',' -f1) + extra_props="" + remaining=$(echo "${version_line}" | cut -d',' -f2- -s) + if [[ -n "${remaining}" ]]; then + IFS=',' read -ra props <<< "${remaining}" + for prop in "${props[@]}"; do + extra_props="${extra_props} -D${prop}" + done + fi + testcase_name="${scenario_name}-${version}" # testcase working directory, there are logs, data and packages. @@ -245,7 +258,7 @@ do cp ./config/expectedData.yaml ${case_work_base}/data # echo "build ${testcase_name}" - ${mvnw} -q --batch-mode clean package -Dtest.framework.version=${version} && \ + ${mvnw} -q --batch-mode clean package -Dtest.framework.version=${version} ${extra_props} && \ mv ./target/${scenario_name}.* ${case_work_base} java -jar \ diff --git a/test/plugin/scenarios/feign-scenario/support-version.list b/test/plugin/scenarios/feign-scenario/support-version.list index 54e90a79ca..eb3667e110 100644 --- a/test/plugin/scenarios/feign-scenario/support-version.list +++ b/test/plugin/scenarios/feign-scenario/support-version.list @@ -20,3 +20,6 @@ 9.3.1 9.4.0 9.5.1 +10.12 +11.10 +12.1 diff --git a/test/plugin/scenarios/graphql-16plus-scenario/support-version.list b/test/plugin/scenarios/graphql-16plus-scenario/support-version.list index c8a4778deb..3d9f037eba 100644 --- a/test/plugin/scenarios/graphql-16plus-scenario/support-version.list +++ b/test/plugin/scenarios/graphql-16plus-scenario/support-version.list @@ -15,6 +15,9 @@ # limitations under the License. # lists your version here +# graphql-java 20+ requires Java 11+, so only 16-19 are tested here (Java 8 scenario) 16.0 17.0 +18.7 +19.11 diff --git a/test/plugin/scenarios/graphql-20plus-scenario/bin/startup.sh b/test/plugin/scenarios/graphql-20plus-scenario/bin/startup.sh new file mode 100644 index 0000000000..aba240987a --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-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/graphql-20plus-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/graphql-20plus-scenario/config/expectedData.yaml b/test/plugin/scenarios/graphql-20plus-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..df3b3315ec --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/config/expectedData.yaml @@ -0,0 +1,88 @@ +# 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: graphql-20plus-scenario + segmentSize: gt 1 + segments: + - segmentId: not null + spans: + - operationName: user + parentSpanId: 0 + spanId: 1 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 92 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: x-le, value: '{"logic-span":true}'} + - operationName: users + parentSpanId: 0 + spanId: 2 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 92 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: x-le, value: '{"logic-span":true}'} + - operationName: user + parentSpanId: 0 + spanId: 3 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 92 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: x-le, value: '{"logic-span":true}'} + - operationName: users + parentSpanId: 0 + spanId: 4 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 92 + isError: false + spanType: Local + peer: '' + skipAnalysis: false + tags: + - {key: x-le, value: '{"logic-span":true}'} + - operationName: GET:/graphql-scenario/case/graphql + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/graphql-scenario/case/graphql'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/graphql-20plus-scenario/configuration.yml b/test/plugin/scenarios/graphql-20plus-scenario/configuration.yml new file mode 100644 index 0000000000..9032d2abff --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/configuration.yml @@ -0,0 +1,20 @@ +# 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/graphql-scenario/case/graphql +healthCheck: http://localhost:8080/graphql-scenario/case/healthCheck +startScript: ./bin/startup.sh diff --git a/test/plugin/scenarios/graphql-20plus-scenario/pom.xml b/test/plugin/scenarios/graphql-20plus-scenario/pom.xml new file mode 100644 index 0000000000..d1daa8b2a4 --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/pom.xml @@ -0,0 +1,117 @@ + + + + + org.apache.skywalking.apm.testcase + graphql-20plus-scenario + 1.0.0 + jar + + 4.0.0 + + skywalking-graphql-20plus-scenario + + + UTF-8 + 17 + 3.8.1 + 3.0.13 + 20.0 + 1.18.30 + graphql + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + com.graphql-java + graphql-java + ${test.framework.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + org.springframework.boot + spring-boot-starter-web + + + + + graphql-20plus-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + diff --git a/test/plugin/scenarios/graphql-20plus-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/graphql-20plus-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..8366461a93 --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/graphql-20plus-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/Application.java b/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/Application.java new file mode 100644 index 0000000000..657ca45983 --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/Application.java @@ -0,0 +1,29 @@ +/* + * 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.testcase.graphql; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/configuration/GraphSchema.java b/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/configuration/GraphSchema.java new file mode 100644 index 0000000000..607fdf7222 --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/configuration/GraphSchema.java @@ -0,0 +1,120 @@ +/* + * 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.testcase.graphql.configuration; + +import graphql.GraphQL; +import graphql.schema.GraphQLFieldDefinition; +import graphql.schema.GraphQLList; +import graphql.schema.GraphQLOutputType; +import graphql.schema.GraphQLSchema; +import org.apache.skywalking.apm.testcase.graphql.data.User; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +import jakarta.annotation.PostConstruct; +import java.util.ArrayList; +import java.util.List; + +import static graphql.Scalars.GraphQLInt; +import static graphql.Scalars.GraphQLString; +import static graphql.schema.GraphQLArgument.newArgument; +import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; +import static graphql.schema.GraphQLObjectType.newObject; + +@Component +public class GraphSchema { + private graphql.schema.GraphQLSchema schema; + private GraphQLOutputType userType; + + @PostConstruct + public void init() { + initOutputType(); + schema = graphql.schema.GraphQLSchema.newSchema().query(newObject() + .name("GraphQuery") + .field(createUsersField()) + .field(createUserField()) + .build()).build(); + } + + @Bean + public GraphQL graphQL() { + return new GraphQL.Builder(getSchema()).build(); + } + + private void initOutputType() { + + userType = newObject() + .name("User") + .field(newFieldDefinition().name("id").type(GraphQLInt).build()) + .field(newFieldDefinition().name("name").type(GraphQLString).build()) + .build(); + } + + private GraphQLFieldDefinition createUserField() { + return GraphQLFieldDefinition.newFieldDefinition() + .name("user") + .argument(newArgument().name("id").type(GraphQLInt).build()) + .type(userType) + .dataFetcher(environment -> { + int id = environment.getArgument("id"); + try { + Thread.sleep(300L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + User user = new User(); + user.setId(id); + user.setName("Name_" + id); + return user; + }) + .build(); + } + + private GraphQLFieldDefinition createUsersField() { + return GraphQLFieldDefinition.newFieldDefinition() + .name("users") + .argument(newArgument().name("page").type(GraphQLInt).build()) + .argument(newArgument().name("size").type(GraphQLInt).build()) + .argument(newArgument().name("name").type(GraphQLString).build()) + .type(new GraphQLList(userType)) + .dataFetcher(environment -> { + int page = environment.getArgument("page"); + int size = environment.getArgument("size"); + String name = environment.getArgument("name"); + + try { + Thread.sleep(100L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + List list = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + User user = new User(); + user.setId(i); + user.setName(name + "_" + page + "_" + i); + list.add(user); + } + return list; + }) + .build(); + } + + public GraphQLSchema getSchema() { + return schema; + } +} \ No newline at end of file diff --git a/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/controller/CaseController.java b/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/controller/CaseController.java new file mode 100644 index 0000000000..a014af2ae4 --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/controller/CaseController.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.testcase.graphql.controller; + +import graphql.ExecutionInput; +import graphql.GraphQL; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.annotation.Resource; + +@RestController +@RequestMapping("/case") +public class CaseController { + + private static final String SUCCESS = "Success"; + + @Resource + private GraphQL graphQL; + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + return SUCCESS; + } + + @RequestMapping("/graphql") + @ResponseBody + public String graphql() { + String query3 = "{user(id:6) {id,name},users(page:2,size:5,name:\"john\") {id,name}}"; + ExecutionInput executionInput = ExecutionInput.newExecutionInput().query(query3).build(); + graphQL.execute(executionInput); + graphQL.executeAsync(executionInput); + return SUCCESS; + } +} diff --git a/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/data/User.java b/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/data/User.java new file mode 100644 index 0000000000..c23a2baf3f --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/src/main/java/org/apache/skywalking/apm/testcase/graphql/data/User.java @@ -0,0 +1,26 @@ +/* + * 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.testcase.graphql.data; + +import lombok.Data; + +@Data +public class User { + private int id; + private String name; +} \ No newline at end of file diff --git a/test/plugin/scenarios/graphql-20plus-scenario/src/main/resources/application.yml b/test/plugin/scenarios/graphql-20plus-scenario/src/main/resources/application.yml new file mode 100644 index 0000000000..3d9f580c4e --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/src/main/resources/application.yml @@ -0,0 +1,20 @@ +# 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 + servlet: + context-path: /graphql-scenario \ No newline at end of file diff --git a/test/plugin/scenarios/graphql-20plus-scenario/support-version.list b/test/plugin/scenarios/graphql-20plus-scenario/support-version.list new file mode 100644 index 0000000000..0d28512b2e --- /dev/null +++ b/test/plugin/scenarios/graphql-20plus-scenario/support-version.list @@ -0,0 +1,23 @@ +# 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. + +# graphql-java 20+ requires Java 11+, tested with JDK 17 + +20.9 +21.5 +22.4 +23.1 +24.1 diff --git a/test/plugin/scenarios/mariadb-scenario/support-version.list b/test/plugin/scenarios/mariadb-scenario/support-version.list index 8d642a99e3..09e354a134 100644 --- a/test/plugin/scenarios/mariadb-scenario/support-version.list +++ b/test/plugin/scenarios/mariadb-scenario/support-version.list @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +2.7.12 2.6.0 2.5.4 2.4.4 diff --git a/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list b/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list index 68dfcd9852..d48bca9d2d 100644 --- a/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list +++ b/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list @@ -15,4 +15,13 @@ # limitations under the License. 4.0.5 -4.1.0 \ No newline at end of file +4.1.0 +4.2.3 +4.3.4 +4.4.2 +4.5.1 +4.6.1 +4.7.2 +4.8.2 +4.9.1 +4.10.2 \ No newline at end of file diff --git a/test/plugin/scenarios/mysql-9.x-scenario/bin/startup.sh b/test/plugin/scenarios/mysql-9.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..7e4ac0fd1d --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-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/mysql-9.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/mysql-9.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/mysql-9.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..17f823f911 --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/config/expectedData.yaml @@ -0,0 +1,151 @@ +# 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: mysql-9.x-scenario + segmentSize: ge 2 + segments: + - segmentId: not null + spans: + - operationName: Mysql/JDBC/PreparedStatement/execute + parentSpanId: 0 + spanId: 1 + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - key: db.statement + value: "CREATE TABLE test_007(\nid VARCHAR(1) PRIMARY KEY, \nvalue VARCHAR(1)\ + \ NOT NULL)" + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 33 + peer: mysql-server:3306 + skipAnalysis: 'false' + - operationName: Mysql/JDBC/PreparedStatement/execute + parentSpanId: 0 + spanId: 2 + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - {key: db.statement, value: 'INSERT INTO test_007(id, value) VALUES(?,?)'} + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 33 + peer: mysql-server:3306 + skipAnalysis: 'false' + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 3 + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - {key: db.statement, value: DROP table test_007} + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 33 + peer: mysql-server:3306 + skipAnalysis: 'false' + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 4 + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - {key: db.statement, value: "create procedure testProcedure(IN id varchar(10)) \n begin \n select id; \n end"} + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 33 + peer: mysql-server:3306 + skipAnalysis: 'false' + # MySQL Connector 8.4+ no longer issues internal SHOW CREATE PROCEDURE query + - operationName: Mysql/JDBC/CallableStatement/execute + parentSpanId: 0 + spanId: 5 + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - {key: db.statement, value: "call testProcedure( ? )"} + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 33 + peer: mysql-server:3306 + skipAnalysis: 'false' + - operationName: Mysql/JDBC/Statement/execute + parentSpanId: 0 + spanId: 6 + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - {key: db.statement, value: "drop procedure testProcedure"} + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 33 + peer: mysql-server:3306 + skipAnalysis: 'false' + - operationName: Mysql/JDBC/Connection/close + parentSpanId: 0 + spanId: 7 + tags: + - {key: db.type, value: Mysql} + - {key: db.instance, value: test} + - {key: db.statement, value: ''} + logs: [] + startTime: nq 0 + endTime: nq 0 + isError: false + spanLayer: Database + spanType: Exit + componentId: 33 + peer: mysql-server:3306 + skipAnalysis: 'false' + - operationName: GET:/mysql-scenario/case/mysql-scenario + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + spanLayer: Http + isError: false + spanType: Entry + componentId: 1 + tags: + - {key: url, value: 'http://localhost:8080/mysql-scenario/case/mysql-scenario'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + logs: [] + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/mysql-9.x-scenario/configuration.yml b/test/plugin/scenarios/mysql-9.x-scenario/configuration.yml new file mode 100644 index 0000000000..0d486ac74b --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/configuration.yml @@ -0,0 +1,32 @@ +# 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/mysql-scenario/case/mysql-scenario +healthCheck: http://localhost:8080/mysql-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: +depends_on: + - mysql-server +dependencies: + mysql-server: + image: mysql:8.0 + hostname: mysql-server + expose: + - "3306" + environment: + - MYSQL_ROOT_PASSWORD=root + - MYSQL_DATABASE=test diff --git a/test/plugin/scenarios/mysql-9.x-scenario/pom.xml b/test/plugin/scenarios/mysql-9.x-scenario/pom.xml new file mode 100644 index 0000000000..c99900594a --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/pom.xml @@ -0,0 +1,123 @@ + + + + + org.apache.skywalking.apm.testcase + mysql-9.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + + 9.0.0 + ${test.framework.version} + + 2.1.6.RELEASE + + + skywalking-mysql-9.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + com.mysql + mysql-connector-j + ${test.framework.version} + + + + + mysql-9.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${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/mysql-9.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/mysql-9.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..9aae4e672b --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/mysql-9.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/Application.java b/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/Application.java new file mode 100644 index 0000000000..b7d42e6fc2 --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/Application.java @@ -0,0 +1,34 @@ +/* + * 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.testcase.mysql; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } +} diff --git a/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/MysqlConfig.java b/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/MysqlConfig.java new file mode 100644 index 0000000000..f30a6ebc37 --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/MysqlConfig.java @@ -0,0 +1,58 @@ +/* + * 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.testcase.mysql; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class MysqlConfig { + private static final Logger LOGGER = LogManager.getLogger(MysqlConfig.class); + private static String URL; + private static String USER_NAME; + private static String PASSWORD; + + static { + InputStream inputStream = MysqlConfig.class.getClassLoader().getResourceAsStream("/jdbc.properties"); + Properties properties = new Properties(); + try { + properties.load(inputStream); + } catch (IOException e) { + LOGGER.error("Failed to load config", e); + } + + URL = properties.getProperty("mysql.url"); + USER_NAME = properties.getProperty("mysql.username"); + PASSWORD = properties.getProperty("mysql.password"); + } + + public static String getUrl() { + return URL; + } + + public static String getUserName() { + return USER_NAME; + } + + public static String getPassword() { + return PASSWORD; + } +} diff --git a/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/SQLExecutor.java b/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/SQLExecutor.java new file mode 100644 index 0000000000..74e3d12d6c --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/SQLExecutor.java @@ -0,0 +1,88 @@ +/* + * 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.testcase.mysql; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +public class SQLExecutor implements AutoCloseable { + private Connection connection; + + public SQLExecutor() throws SQLException { + try { + Class.forName("com.mysql.cj.jdbc.Driver"); + } catch (ClassNotFoundException e) { + // + } + connection = DriverManager.getConnection(MysqlConfig.getUrl(), MysqlConfig.getUserName(), MysqlConfig.getPassword()); + } + + public void createTable(String sql) throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement(sql); + preparedStatement.execute(); + preparedStatement.close(); + } + + public void insertData(String sql, String id, String value) throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement(sql); + preparedStatement.setString(1, id); + preparedStatement.setString(2, value); + preparedStatement.execute(); + preparedStatement.close(); + } + + public void dropTable(String sql) throws SQLException { + executeStatement(sql); + } + + public void createProcedure(String sql) throws SQLException { + executeStatement(sql); + } + + public void dropProcedure(String sql) throws SQLException { + executeStatement(sql); + } + + public void callProcedure(String sql, String id) throws SQLException { + PreparedStatement preparedStatement = connection.prepareCall(sql); + preparedStatement.setString(1, id); + preparedStatement.execute(); + preparedStatement.close(); + } + + public void executeStatement(String sql) throws SQLException { + Statement preparedStatement = connection.createStatement(); + preparedStatement.execute(sql); + preparedStatement.close(); + } + + public void closeConnection() throws SQLException { + if (this.connection != null) { + this.connection.close(); + } + } + + @Override + public void close() throws Exception { + closeConnection(); + } +} diff --git a/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/controller/CaseController.java b/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/controller/CaseController.java new file mode 100644 index 0000000000..626ef9a190 --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mysql/controller/CaseController.java @@ -0,0 +1,71 @@ +/* + * 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.testcase.mysql.controller; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.mysql.SQLExecutor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +public class CaseController { + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + private static final String SUCCESS = "Success"; + + private static final String CREATE_TABLE_SQL = "CREATE TABLE test_007(\n" + "id VARCHAR(1) PRIMARY KEY, \n" + "value VARCHAR(1) NOT NULL)"; + private static final String INSERT_DATA_SQL = "INSERT INTO test_007(id, value) VALUES(?,?)"; + private static final String QUERY_DATA_SQL = "SELECT id, value FROM test_007 WHERE id=?"; + private static final String DELETE_DATA_SQL = "DELETE FROM test_007 WHERE id=?"; + private static final String DROP_TABLE_SQL = "DROP table test_007"; + private static final String CREATE_PROCEDURE_SQL = "create procedure testProcedure(IN id varchar(10)) \n begin \n select id; \n end"; + private static final String CALL_PROCEDURE_SQL = "call testProcedure( ? )"; + private static final String DROP_PROCEDURE_SQL = "drop procedure testProcedure"; + + @RequestMapping("/mysql-scenario") + @ResponseBody + public String testcase() throws Exception { + try (SQLExecutor sqlExecute = new SQLExecutor()) { + sqlExecute.createTable(CREATE_TABLE_SQL); + sqlExecute.insertData(INSERT_DATA_SQL, "1", "1"); + sqlExecute.dropTable(DROP_TABLE_SQL); + sqlExecute.createProcedure(CREATE_PROCEDURE_SQL); + sqlExecute.callProcedure(CALL_PROCEDURE_SQL, "nihao"); + sqlExecute.dropProcedure(DROP_PROCEDURE_SQL); + } catch (Exception e) { + LOGGER.error("Failed to execute sql.", e); + throw e; + } + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() throws Exception { + try (SQLExecutor sqlExecutor = new SQLExecutor()) { + // ignore + } + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..8dc5e28d15 --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +# +# 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 + servlet: + context-path: /mysql-scenario +logging: + config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/jdbc.properties b/test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/jdbc.properties new file mode 100644 index 0000000000..7d999c28da --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/jdbc.properties @@ -0,0 +1,18 @@ +# 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. +mysql.url=jdbc:mysql://mysql-server:3306/test?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true +mysql.username=root +mysql.password=root diff --git a/test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/mysql-9.x-scenario/support-version.list b/test/plugin/scenarios/mysql-9.x-scenario/support-version.list new file mode 100644 index 0000000000..d0f41f5673 --- /dev/null +++ b/test/plugin/scenarios/mysql-9.x-scenario/support-version.list @@ -0,0 +1,25 @@ +# 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. + +# Uses com.mysql:mysql-connector-j artifact (8.0.31+ and 9.x) +8.4.0 +9.0.0 +9.1.0 +9.2.0 +9.3.0 +9.4.0 +9.5.0 +9.6.0 diff --git a/test/plugin/scenarios/mysql-scenario/support-version.list b/test/plugin/scenarios/mysql-scenario/support-version.list index 746fa92395..b0b1761ebb 100644 --- a/test/plugin/scenarios/mysql-scenario/support-version.list +++ b/test/plugin/scenarios/mysql-scenario/support-version.list @@ -14,6 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# 8.0.30+ requires allowPublicKeyRetrieval=true and serverTimezone=UTC +# Those versions are tested in mysql-9.x-scenario with the fixed JDBC URL 8.0.19 8.0.15 6.0.6 diff --git a/test/plugin/scenarios/spring-kafka-1.3.x-scenario/configuration.yml b/test/plugin/scenarios/spring-kafka-1.3.x-scenario/configuration.yml index 8d387e2d45..8ff824fa43 100644 --- a/test/plugin/scenarios/spring-kafka-1.3.x-scenario/configuration.yml +++ b/test/plugin/scenarios/spring-kafka-1.3.x-scenario/configuration.yml @@ -25,7 +25,7 @@ depends_on: - kafka-server dependencies: zookeeper-server: - image: zookeeper:3.4 + image: zookeeper:3.7 hostname: zookeeper-server kafka-server: image: bitnamilegacy/kafka:2.4.1 diff --git a/test/plugin/scenarios/spring-kafka-2.2.x-scenario/configuration.yml b/test/plugin/scenarios/spring-kafka-2.2.x-scenario/configuration.yml index 164b29135a..3728f3a9cb 100644 --- a/test/plugin/scenarios/spring-kafka-2.2.x-scenario/configuration.yml +++ b/test/plugin/scenarios/spring-kafka-2.2.x-scenario/configuration.yml @@ -25,7 +25,7 @@ depends_on: - kafka-server dependencies: zookeeper-server: - image: zookeeper:3.4 + image: zookeeper:3.7 hostname: zookeeper-server kafka-server: image: bitnamilegacy/kafka:2.4.1 diff --git a/test/plugin/scenarios/spring-kafka-2.3.x-scenario/configuration.yml b/test/plugin/scenarios/spring-kafka-2.3.x-scenario/configuration.yml index 295f967541..8948c60ab6 100644 --- a/test/plugin/scenarios/spring-kafka-2.3.x-scenario/configuration.yml +++ b/test/plugin/scenarios/spring-kafka-2.3.x-scenario/configuration.yml @@ -25,7 +25,7 @@ depends_on: - kafka-server dependencies: zookeeper-server: - image: zookeeper:3.4 + image: zookeeper:3.7 hostname: zookeeper-server kafka-server: image: bitnamilegacy/kafka:2.4.1 diff --git a/test/plugin/scenarios/spring-kafka-2.3.x-scenario/pom.xml b/test/plugin/scenarios/spring-kafka-2.3.x-scenario/pom.xml index cb1b20edd5..822455c920 100644 --- a/test/plugin/scenarios/spring-kafka-2.3.x-scenario/pom.xml +++ b/test/plugin/scenarios/spring-kafka-2.3.x-scenario/pom.xml @@ -55,17 +55,8 @@ - - org.apache.kafka - kafka-clients - ${kafka-version} - - - slf4j-api - * - - - + com.squareup.okhttp3 okhttp diff --git a/test/plugin/scenarios/spring-kafka-2.3.x-scenario/support-version.list b/test/plugin/scenarios/spring-kafka-2.3.x-scenario/support-version.list index 6859d9a3bb..126ffe549e 100644 --- a/test/plugin/scenarios/spring-kafka-2.3.x-scenario/support-version.list +++ b/test/plugin/scenarios/spring-kafka-2.3.x-scenario/support-version.list @@ -14,4 +14,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Format: spring-kafka-version[,key=value] — extra properties passed to Maven. +# Spring Boot autoconfigure must match the spring-kafka version's expected APIs. +# Mapping: https://spring.io/projects/spring-kafka#overview (compatibility matrix) 2.3.10.RELEASE +2.4.13.RELEASE +2.5.17.RELEASE +2.6.13 +2.7.14,spring.boot.version=2.5.15 +2.8.11,spring.boot.version=2.7.18 +2.9.13,spring.boot.version=2.7.18 diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/bin/startup.sh b/test/plugin/scenarios/spring-kafka-3.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..5a10cdccba --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-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 -Dbootstrap.servers=${BOOTSTRAP_SERVERS} -jar ${agent_opts} "-Dskywalking.agent.service_name=spring-kafka-3.x-scenario" ${home}/../libs/spring-kafka-3.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-kafka-3.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..f58e28b78d --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-scenario/config/expectedData.yaml @@ -0,0 +1,123 @@ +# 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: spring-kafka-3.x-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: Kafka/spring_test/Producer + parentSpanId: 0 + spanId: 1 + spanLayer: MQ + startTime: not null + endTime: not null + componentId: 40 + isError: false + spanType: Exit + peer: kafka-server:9092 + skipAnalysis: false + tags: + - {key: mq.broker, value: 'kafka-server:9092'} + - {key: mq.topic, value: spring_test} + - operationName: Kafka/spring_test/Producer + parentSpanId: 0 + spanId: 2 + spanLayer: MQ + startTime: not null + endTime: not null + componentId: 40 + isError: false + spanType: Exit + peer: kafka-server:9092 + skipAnalysis: false + tags: + - { key: mq.broker, value: 'kafka-server:9092' } + - { key: mq.topic, value: spring_test } + - operationName: GET:/spring-kafka-3.x-scenario/case/spring-kafka-case + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/spring-kafka-3.x-scenario/case/spring-kafka-case'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + - segmentId: not null + spans: + - operationName: GET:/spring-kafka-3.x-scenario/case/spring-kafka-consumer-ping + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/spring-kafka-3.x-scenario/case/spring-kafka-consumer-ping'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: 'Kafka/spring_test/Consumer/grop:spring_test', networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: spring-kafka-3.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: /spring-kafka-3.x-scenario/case/spring-kafka-consumer-ping + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + skipAnalysis: false + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-kafka-3.x-scenario/case/spring-kafka-consumer-ping'} + - {key: http.status_code, value: '200'} + - operationName: Kafka/spring_test/Consumer/grop:spring_test + parentSpanId: -1 + spanId: 0 + spanLayer: MQ + startTime: not null + endTime: not null + componentId: 41 + isError: false + spanType: Entry + peer: kafka-server:9092 + skipAnalysis: false + tags: + - {key: mq.broker, value: 'kafka-server:9092'} + - {key: mq.topic, value: spring_test} + - {key: transmission.latency, value: not null} + refs: + - {parentEndpoint: 'GET:/spring-kafka-3.x-scenario/case/spring-kafka-case', networkAddress: 'kafka-server:9092', + refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: spring-kafka-3.x-scenario, + traceId: not null} diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/configuration.yml b/test/plugin/scenarios/spring-kafka-3.x-scenario/configuration.yml new file mode 100644 index 0000000000..1397670aff --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-scenario/configuration.yml @@ -0,0 +1,39 @@ +# 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/spring-kafka-3.x-scenario/case/spring-kafka-case +healthCheck: http://localhost:8080/spring-kafka-3.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: + - BOOTSTRAP_SERVERS=kafka-server:9092 +depends_on: + - zookeeper-server + - kafka-server +dependencies: + zookeeper-server: + image: zookeeper:3.7 + hostname: zookeeper-server + kafka-server: + image: bitnamilegacy/kafka:2.4.1 + hostname: kafka-server + environment: + - KAFKA_ZOOKEEPER_CONNECT=zookeeper-server:2181 + - KAFKA_BROKER_ID=1 + - ALLOW_PLAINTEXT_LISTENER=yes + - KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 + depends_on: + - zookeeper-server diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/pom.xml b/test/plugin/scenarios/spring-kafka-3.x-scenario/pom.xml new file mode 100644 index 0000000000..2e6a5200a4 --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-scenario/pom.xml @@ -0,0 +1,134 @@ + + + + 4.0.0 + + org.apache.skywalking + spring-kafka-3.x-scenario + 5.0.0 + + + UTF-8 + 17 + 3.8.1 + 3.0.0 + 2.6.2 + 3.2.12 + 3.3.2 + 3.0.0 + + + skywalking-spring-kafka-3.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.kafka + spring-kafka + ${test.framework.version} + + + org.slf4j + * + + + + + + com.squareup.okhttp3 + okhttp + ${okhttp-version} + + + + + spring-kafka-3.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + + + + spring-snapshots + https://repo.spring.io/snapshot + + + spring-milestones + https://repo.spring.io/milestone + + + diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..567e5690ed --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/spring-kafka-3.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring/kafka/Application.java b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring/kafka/Application.java new file mode 100644 index 0000000000..56eb4f0b97 --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring/kafka/Application.java @@ -0,0 +1,30 @@ +/* + * 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.spring.kafka; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring/kafka/controller/CaseController.java b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring/kafka/controller/CaseController.java new file mode 100644 index 0000000000..6044346ae9 --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring/kafka/controller/CaseController.java @@ -0,0 +1,159 @@ +/* + * 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.spring.kafka.controller; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.serialization.Deserializer; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.listener.AcknowledgingMessageListener; +import org.springframework.kafka.listener.ContainerProperties; +import org.springframework.kafka.listener.KafkaMessageListenerContainer; +import org.springframework.kafka.support.Acknowledgment; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import jakarta.annotation.PostConstruct; +import java.util.Arrays; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; + +@Controller +@RequestMapping("/case") +@PropertySource("classpath:application.properties") +public class CaseController { + + private static final String SUCCESS = "Success"; + + @Value("${bootstrap.servers:127.0.0.1:9092}") + private String bootstrapServers; + private String topicName; + private KafkaTemplate kafkaTemplate; + private KafkaTemplate kafkaTemplate2; + + private CountDownLatch latch; + private String helloWorld = "helloWorld"; + + @PostConstruct + private void setUp() { + topicName = "spring_test"; + setUpProvider(); + setUpAnotherProvider(); + setUpConsumer(); + } + + private void setUpProvider() { + Map props = new HashMap<>(); + props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + kafkaTemplate = new KafkaTemplate(new DefaultKafkaProducerFactory<>(props)); + try { + kafkaTemplate.send(topicName, "key", "ping").get(); + kafkaTemplate.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void setUpAnotherProvider() { + Map props = new HashMap<>(); + // use list type here + props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, Arrays.asList(bootstrapServers.split(","))); + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + kafkaTemplate2 = new KafkaTemplate(new DefaultKafkaProducerFactory<>(props)); + try { + kafkaTemplate2.send(topicName, "key", "ping").get(); + kafkaTemplate2.flush(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void setUpConsumer() { + Map configs = new HashMap<>(); + configs.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers); + configs.put(ConsumerConfig.GROUP_ID_CONFIG, "grop:" + topicName); + configs.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); + Deserializer stringDeserializer = new StringDeserializer(); + DefaultKafkaConsumerFactory factory = new DefaultKafkaConsumerFactory(configs, stringDeserializer, stringDeserializer); + ContainerProperties props = new ContainerProperties(topicName); + props.setMessageListener(new AcknowledgingMessageListener() { + @Override + public void onMessage(ConsumerRecord data, Acknowledgment acknowledgment) { + if (data.value().equals(helloWorld)) { + OkHttpClient client = new OkHttpClient.Builder().build(); + Request request = new Request.Builder().url("http://localhost:8080/spring-kafka-3.x-scenario/case/spring-kafka-consumer-ping").build(); + Response response = null; + try { + response = client.newCall(request).execute(); + } catch (IOException e) { + } + response.body().close(); + acknowledgment.acknowledge(); + latch.countDown(); + } + } + }); + KafkaMessageListenerContainer container = new KafkaMessageListenerContainer<>(factory, props); + container.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE); + container.start(); + } + + @RequestMapping("/spring-kafka-case") + @ResponseBody + public String springKafkaCase() throws Exception { + this.latch = new CountDownLatch(1); + kafkaTemplate.send(topicName, "key", helloWorld).get(); + this.latch.await(); + kafkaTemplate.flush(); + this.latch = new CountDownLatch(1); + kafkaTemplate2.send(topicName, "key", helloWorld).get(); + this.latch.await(); + kafkaTemplate2.flush(); + return SUCCESS; + } + + @RequestMapping("/spring-kafka-consumer-ping") + @ResponseBody + public String springKafkaConsumerPing() { + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + return SUCCESS; + } +} + diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/resources/application.properties b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/resources/application.properties new file mode 100644 index 0000000000..09a297f5b4 --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/resources/application.properties @@ -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 +server.servlet.context-path=/spring-kafka-3.x-scenario \ No newline at end of file diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..b5cda5ae8a --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/test/plugin/scenarios/spring-kafka-3.x-scenario/support-version.list b/test/plugin/scenarios/spring-kafka-3.x-scenario/support-version.list new file mode 100644 index 0000000000..3f547d82e4 --- /dev/null +++ b/test/plugin/scenarios/spring-kafka-3.x-scenario/support-version.list @@ -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. + +# Spring Kafka 3.x requires Spring Boot 3.x / JDK 17+ +# This scenario uses Spring Boot 3.1.12 BOM (Spring Framework 6.1). +# spring-kafka 3.0.x not tested here (needs Spring Boot 3.0 — covered by separate scenario if needed). +3.1.4 +3.2.10 +3.3.7 diff --git a/test/plugin/scenarios/undertow-2.3.x-scenario/bin/startup.sh b/test/plugin/scenarios/undertow-2.3.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..e7e48dc3b2 --- /dev/null +++ b/test/plugin/scenarios/undertow-2.3.x-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/undertow-2.3.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/undertow-2.3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/undertow-2.3.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..b364557b9f --- /dev/null +++ b/test/plugin/scenarios/undertow-2.3.x-scenario/config/expectedData.yaml @@ -0,0 +1,142 @@ +# 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: undertow-2.3.x-scenario + segmentSize: gt 5 + segments: + - segmentId: not null + spans: + - operationName: GET:/undertow-scenario/case/undertow + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 84 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/undertow-scenario/case/undertow'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GET:/undertow-routing-scenario/case/{context} + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 84 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8081/undertow-routing-scenario/case/undertow'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: UndertowDispatch, networkAddress: 'localhost:8081', refType: CrossProcess, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: undertow-2.3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GET:/undertow-scenario/case/undertow1 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 84 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/undertow-scenario/case/undertow1'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: UndertowDispatch, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: undertow-2.3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: /undertow-routing-scenario/case/undertow + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 2 + isError: false + spanType: Exit + peer: localhost:8081 + tags: + - {key: url, value: 'http://localhost:8081/undertow-routing-scenario/case/undertow?send=httpHandler'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: UndertowDispatch + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 84 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: GET:/undertow-scenario/case/undertow, networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: /undertow-scenario/case/undertow1 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 2 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/undertow-scenario/case/undertow1?send=runnable'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: UndertowDispatch + parentSpanId: -1 + spanId: 0 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 84 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: 'GET:/undertow-routing-scenario/case/{context}', networkAddress: '', + refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: undertow-2.3.x-scenario, traceId: not null} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/undertow-2.3.x-scenario/configuration.yml b/test/plugin/scenarios/undertow-2.3.x-scenario/configuration.yml new file mode 100644 index 0000000000..3994b092f8 --- /dev/null +++ b/test/plugin/scenarios/undertow-2.3.x-scenario/configuration.yml @@ -0,0 +1,20 @@ +# 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/undertow-scenario/case/undertow +healthCheck: http://localhost:8080/undertow-scenario/case/healthCheck +startScript: ./bin/startup.sh diff --git a/test/plugin/scenarios/undertow-2.3.x-scenario/pom.xml b/test/plugin/scenarios/undertow-2.3.x-scenario/pom.xml new file mode 100644 index 0000000000..736443dea5 --- /dev/null +++ b/test/plugin/scenarios/undertow-2.3.x-scenario/pom.xml @@ -0,0 +1,118 @@ + + + + 4.0.0 + + org.apache.skywalking + undertow-2.3.x-scenario + jar + 5.0.0 + + + UTF-8 + 11 + 3.8.1 + org.apache.skywalking.amp.testcase.undertow.Application + + undertow + 2.3.0.Final + 2.1.6.RELEASE + + + skywalking-undertow-2.3.x-scenario + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + io.undertow + undertow-core + ${test.framework.version} + + + + org.apache.httpcomponents + httpclient + 4.3 + + + + + undertow-2.3.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + + + + spring-snapshots + https://repo.spring.io/snapshot + + + spring-milestones + https://repo.spring.io/milestone + + + diff --git a/test/plugin/scenarios/undertow-2.3.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/undertow-2.3.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..443828cfcf --- /dev/null +++ b/test/plugin/scenarios/undertow-2.3.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/undertow-2.3.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/undertow-2.3.x-scenario/src/main/java/org/apache/skywalking/amp/testcase/undertow/Application.java b/test/plugin/scenarios/undertow-2.3.x-scenario/src/main/java/org/apache/skywalking/amp/testcase/undertow/Application.java new file mode 100644 index 0000000000..fd45a07d01 --- /dev/null +++ b/test/plugin/scenarios/undertow-2.3.x-scenario/src/main/java/org/apache/skywalking/amp/testcase/undertow/Application.java @@ -0,0 +1,94 @@ +/* + * 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.amp.testcase.undertow; + +import io.undertow.Undertow; +import io.undertow.server.HttpHandler; +import io.undertow.server.RoutingHandler; +import io.undertow.util.Headers; +import io.undertow.util.Methods; +import java.io.IOException; +import org.apache.http.HttpEntity; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +public class Application { + + private static final String CASE_URL = "/undertow-scenario/case/undertow"; + + private static final String TEMPLATE = "/undertow-routing-scenario/case/{context}"; + + private static final String ROUTING_CASE_URL = "/undertow-routing-scenario/case/undertow"; + + public static void main(String[] args) throws InterruptedException { + new Thread(Application::undertowRouting).start(); + undertow(); + } + + private static void undertow() { + Undertow server = Undertow.builder().addHttpListener(8080, "0.0.0.0").setHandler(exchange -> { + if (CASE_URL.equals(exchange.getRequestPath())) { + exchange.dispatch(() -> { + try { + visit("http://localhost:8081/undertow-routing-scenario/case/undertow?send=httpHandler"); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain"); + exchange.getResponseSender().send("Success"); + }).build(); + Runtime.getRuntime().addShutdownHook(new Thread(server::stop)); + server.start(); + } + + private static void undertowRouting() { + HttpHandler httpHandler = exchange -> { + if (ROUTING_CASE_URL.equals(exchange.getRequestPath())) { + exchange.dispatch(httpServerExchange -> visit("http://localhost:8080/undertow-scenario/case/undertow1?send=runnable")); + } + exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain"); + exchange.getResponseSender().send("Success"); + }; + RoutingHandler handler = new RoutingHandler(); + handler.add(Methods.GET, TEMPLATE, httpHandler); + handler.add(Methods.HEAD, TEMPLATE, httpHandler); + Undertow server = Undertow.builder().addHttpListener(8081, "0.0.0.0").setHandler(handler).build(); + Runtime.getRuntime().addShutdownHook(new Thread(server::stop)); + server.start(); + } + + private static void visit(String url) throws IOException { + CloseableHttpClient httpClient = HttpClients.createDefault(); + try { + HttpGet httpget = new HttpGet(url); + ResponseHandler responseHandler = response -> { + HttpEntity entity = response.getEntity(); + return entity != null ? EntityUtils.toString(entity) : null; + }; + httpClient.execute(httpget, responseHandler); + } finally { + httpClient.close(); + } + } +} diff --git a/test/plugin/scenarios/undertow-2.3.x-scenario/support-version.list b/test/plugin/scenarios/undertow-2.3.x-scenario/support-version.list new file mode 100644 index 0000000000..a3dca1ddcf --- /dev/null +++ b/test/plugin/scenarios/undertow-2.3.x-scenario/support-version.list @@ -0,0 +1,18 @@ +# 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. + +# Undertow 2.3.x requires Java 11+, tested with JDK 17 +2.3.18.Final diff --git a/test/plugin/scenarios/undertow-scenario/support-version.list b/test/plugin/scenarios/undertow-scenario/support-version.list index 420cc76010..a6d77253e2 100644 --- a/test/plugin/scenarios/undertow-scenario/support-version.list +++ b/test/plugin/scenarios/undertow-scenario/support-version.list @@ -19,6 +19,9 @@ # 1.3.x 1.4.x: select the first, middle, and last version # 2.0.x: when there are many releases in the same month, choose the last one +# Undertow 2.3.x requires Java 11+, tested in undertow-2.3.x-scenario (JDK 17 workflow) 1.3.33.Final 1.4.27.Final 2.0.27.Final +2.1.8.Final +2.2.37.Final From 1aabdb626ba996e13b3a3ee6ecb169c8acc2b8a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Thu, 9 Apr 2026 13:12:26 +0800 Subject: [PATCH 102/114] Fix MongoDB 4.11+, add Feign 12.2+ PathVar, add MariaDB 3.x plugin, remove PostgreSQL 9.4 from test (#802) --- .github/workflows/plugins-test.3.yaml | 1 + CHANGES.md | 3 + .../v9/define/PathVarV2Instrumentation.java | 79 +++++++++ .../src/main/resources/skywalking-plugin.def | 3 +- .../apm-sdk-plugin/mariadb-3.x-plugin/pom.xml | 60 +++++++ .../CreateCallableStatementInterceptor.java | 49 ++++++ .../CreatePreparedStatementInterceptor.java | 50 ++++++ .../v3/CreateStatementInterceptor.java | 50 ++++++ ...redStatementExecuteMethodsInterceptor.java | 93 +++++++++++ .../mariadb/v3/SetCatalogInterceptor.java | 48 ++++++ .../StatementExecuteMethodsInterceptor.java | 75 +++++++++ .../v3/define/ConnectionInstrumentation.java | 144 +++++++++++++++++ .../v3/define/DriverInstrumentation.java | 36 +++++ ...StatementIgnoredSetterInstrumentation.java | 33 ++++ .../PreparedStatementInstrumentation.java | 74 +++++++++ ...redStatementNullSetterInstrumentation.java | 33 ++++ ...reparedStatementSetterInstrumentation.java | 33 ++++ .../v3/define/StatementInstrumentation.java | 71 ++++++++ .../src/main/resources/skywalking-plugin.def | 23 +++ ...reateCallableStatementInterceptorTest.java | 67 ++++++++ ...reatePreparedStatementInterceptorTest.java | 67 ++++++++ .../v3/CreateStatementInterceptorTest.java | 67 ++++++++ ...tatementExecuteMethodsInterceptorTest.java | 153 ++++++++++++++++++ ...tatementExecuteMethodsInterceptorTest.java | 118 ++++++++++++++ .../v4/support/MongoRemotePeerHelper.java | 2 +- apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 6 +- .../feign-scenario/support-version.list | 2 + .../mariadb-3.x-scenario/bin/startup.sh | 21 +++ .../config/expectedData.yaml | 114 +++++++++++++ .../mariadb-3.x-scenario/configuration.yml | 32 ++++ .../scenarios/mariadb-3.x-scenario/pom.xml | 123 ++++++++++++++ .../src/main/assembly/assembly.xml | 41 +++++ .../apm/testcase/mariadb/Application.java | 39 +++++ .../apm/testcase/mariadb/MariadbConfig.java | 58 +++++++ .../apm/testcase/mariadb/SQLExecutor.java | 70 ++++++++ .../mariadb/controller/CaseController.java | 63 ++++++++ .../src/main/resources/application.yaml | 23 +++ .../src/main/resources/jdbc.properties | 18 +++ .../src/main/resources/log4j2.xml | 30 ++++ .../mariadb-3.x-scenario/support-version.list | 23 +++ .../mongodb-4.x-scenario/support-version.list | 3 +- .../support-version.list | 1 - 44 files changed, 2094 insertions(+), 7 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/feign/http/v9/define/PathVarV2Instrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateCallableStatementInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreatePreparedStatementInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateStatementInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/PreparedStatementExecuteMethodsInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/SetCatalogInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/StatementExecuteMethodsInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/ConnectionInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/DriverInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementIgnoredSetterInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementNullSetterInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementSetterInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/StatementInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateCallableStatementInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreatePreparedStatementInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateStatementInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/PreparedStatementExecuteMethodsInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/StatementExecuteMethodsInterceptorTest.java create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/Application.java create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/MariadbConfig.java create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/SQLExecutor.java create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/controller/CaseController.java create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/jdbc.properties create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/mariadb-3.x-scenario/support-version.list diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index 36ad8289a0..0c667a6d06 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -82,6 +82,7 @@ jobs: - vertx-web-3.54minus-scenario - vertx-web-3.6plus-scenario - mariadb-scenario + - mariadb-3.x-scenario - micronaut-http-scenario - nats-2.14.x-2.16.5-scenario - quasar-scenario diff --git a/CHANGES.md b/CHANGES.md index f55806ecda..bb89a9e688 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,11 +12,14 @@ Release Notes. * Extend MySQL plugin to support MySQL Connector/J 8.4.0 and 9.x (9.0 -> 9.6). * Extend MariaDB plugin to support MariaDB Connector/J 2.7.x. * Extend MongoDB 4.x plugin to support MongoDB Java Driver 4.2 -> 4.10. Fix db.bind_vars extraction for driver 4.9+ where InsertOperation/DeleteOperation/UpdateOperation classes were removed. +* Fix MongoDB 4.x plugin for driver 4.11+ where Cluster.getDescription() was removed, use getCurrentDescription() instead. * Extend Feign plugin to support OpenFeign 10.x, 11.x, 12.1. +* Add Feign 12.2+ PathVar support (BuildTemplateByResolvingArgs moved to RequestTemplateFactoryResolver). * Extend Undertow plugin to support Undertow 2.1.x, 2.2.x, 2.3.x. * Extend GraphQL plugin to support graphql-java 18 -> 24 (20+ requires JDK 17). * Extend Spring Kafka plugin to support Spring Kafka 2.4 -> 2.9 and 3.0 -> 3.3. * Enhance test/plugin/run.sh to support extra Maven properties per version in support-version.list (format: version,key=value). +* Add MariaDB 3.x plugin (all classes renamed in 3.x). All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/feign/http/v9/define/PathVarV2Instrumentation.java b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/feign/http/v9/define/PathVarV2Instrumentation.java new file mode 100644 index 0000000000..434d3c2d55 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/feign/http/v9/define/PathVarV2Instrumentation.java @@ -0,0 +1,79 @@ +/* + * 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.feign.http.v9.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 org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class PathVarV2Instrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + /** + * Enhance class. + */ + private static final String ENHANCE_CLASS = "feign.RequestTemplateFactoryResolver$BuildTemplateByResolvingArgs"; + + /** + * Intercept class. + */ + private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.feign.http.v9.PathVarInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + protected String[] witnessClasses() { + return new String[] {"feign.RequestTemplateFactoryResolver"}; + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("resolve"); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/resources/skywalking-plugin.def index eda47ffa99..778a03f68f 100644 --- a/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/feign-default-http-9.x-plugin/src/main/resources/skywalking-plugin.def @@ -15,4 +15,5 @@ # limitations under the License. feign-default-http-9.x=org.apache.skywalking.apm.plugin.feign.http.v9.define.DefaultHttpClientInstrumentation -feign-pathvar-9.x=org.apache.skywalking.apm.plugin.feign.http.v9.define.PathVarInstrumentation \ No newline at end of file +feign-pathvar-9.x=org.apache.skywalking.apm.plugin.feign.http.v9.define.PathVarInstrumentation +feign-pathvar-9.x=org.apache.skywalking.apm.plugin.feign.http.v9.define.PathVarV2Instrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/pom.xml new file mode 100644 index 0000000000..1011fdda12 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/pom.xml @@ -0,0 +1,60 @@ + + + + + apm-sdk-plugin + org.apache.skywalking + 9.7.0-SNAPSHOT + + 4.0.0 + + apm-mariadb-3.x-plugin + jar + + mariadb-3.x-plugin + http://maven.apache.org + + + UTF-8 + 3.5.1 + + + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb-java-client.version} + provided + + + org.apache.skywalking + apm-jdbc-commons + ${project.version} + provided + + + + + + + maven-deploy-plugin + + + + diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateCallableStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateCallableStatementInterceptor.java new file mode 100644 index 0000000000..e7642c9fbb --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateCallableStatementInterceptor.java @@ -0,0 +1,49 @@ +/* + * 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.jdbc.mariadb.v3; + +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.plugin.jdbc.define.StatementEnhanceInfos; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +import java.lang.reflect.Method; + +public class CreateCallableStatementInterceptor 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 EnhancedInstance) { + ((EnhancedInstance) ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo) objInst.getSkyWalkingDynamicField(), (String) allArguments[0], "CallableStatement")); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreatePreparedStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreatePreparedStatementInterceptor.java new file mode 100644 index 0000000000..a17b112718 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreatePreparedStatementInterceptor.java @@ -0,0 +1,50 @@ +/* + * 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.jdbc.mariadb.v3; + +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.plugin.jdbc.define.StatementEnhanceInfos; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +import java.lang.reflect.Method; + +public class CreatePreparedStatementInterceptor 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 EnhancedInstance) { + ((EnhancedInstance) ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo) objInst.getSkyWalkingDynamicField(), (String) allArguments[0], "PreparedStatement")); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateStatementInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateStatementInterceptor.java new file mode 100644 index 0000000000..036fe00a39 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateStatementInterceptor.java @@ -0,0 +1,50 @@ +/* + * 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.jdbc.mariadb.v3; + +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.plugin.jdbc.define.StatementEnhanceInfos; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +import java.lang.reflect.Method; + +public class CreateStatementInterceptor 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 EnhancedInstance) { + ((EnhancedInstance) ret).setSkyWalkingDynamicField(new StatementEnhanceInfos((ConnectionInfo) objInst.getSkyWalkingDynamicField(), "", "Statement")); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/PreparedStatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/PreparedStatementExecuteMethodsInterceptor.java new file mode 100644 index 0000000000..8ec30304b7 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/PreparedStatementExecuteMethodsInterceptor.java @@ -0,0 +1,93 @@ +/* + * 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.jdbc.mariadb.v3; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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.plugin.jdbc.JDBCPluginConfig; +import org.apache.skywalking.apm.plugin.jdbc.PreparedStatementParameterBuilder; +import org.apache.skywalking.apm.plugin.jdbc.SqlBodyUtil; +import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +import java.lang.reflect.Method; + +public class PreparedStatementExecuteMethodsInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) { + StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField(); + ConnectionInfo connectInfo = cacheObject.getConnectionInfo(); + if (connectInfo == null) { + return; + } + AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject + .getStatementName()), connectInfo.getDatabasePeer()); + Tags.DB_TYPE.set(span, connectInfo.getDBType()); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, SqlBodyUtil.limitSqlBodySize(cacheObject.getSql())); + span.setComponent(connectInfo.getComponent()); + + if (JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS) { + final Object[] parameters = cacheObject.getParameters(); + if (parameters != null && parameters.length > 0) { + int maxIndex = cacheObject.getMaxIndex(); + Tags.SQL_PARAMETERS.set(span, getParameterString(parameters, maxIndex)); + } + } + + SpanLayer.asDB(span); + } + + @Override + public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) { + StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField(); + if (cacheObject.getConnectionInfo() != null) { + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField(); + if (cacheObject.getConnectionInfo() != null) { + ContextManager.activeSpan().log(t); + } + } + + private String buildOperationName(ConnectionInfo connectionInfo, String methodName, String statementName) { + return connectionInfo.getDBType() + "/JDBC/" + statementName + "/" + methodName; + } + + private String getParameterString(Object[] parameters, int maxIndex) { + return new PreparedStatementParameterBuilder() + .setParameters(parameters) + .setMaxIndex(maxIndex) + .build(); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/SetCatalogInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/SetCatalogInterceptor.java new file mode 100644 index 0000000000..48b9b3e926 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/SetCatalogInterceptor.java @@ -0,0 +1,48 @@ +/* + * 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.jdbc.mariadb.v3; + +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.plugin.jdbc.trace.ConnectionInfo; + +import java.lang.reflect.Method; + +public class SetCatalogInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) { + Object dynamicField = objInst.getSkyWalkingDynamicField(); + if (dynamicField instanceof ConnectionInfo) { + ((ConnectionInfo) dynamicField).setDatabaseName(String.valueOf(allArguments[0])); + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) { + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/StatementExecuteMethodsInterceptor.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/StatementExecuteMethodsInterceptor.java new file mode 100644 index 0000000000..c88f921881 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/StatementExecuteMethodsInterceptor.java @@ -0,0 +1,75 @@ +/* + * 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.jdbc.mariadb.v3; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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.plugin.jdbc.SqlBodyUtil; +import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; + +import java.lang.reflect.Method; + +public class StatementExecuteMethodsInterceptor implements InstanceMethodsAroundInterceptor { + @Override + public final void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) { + StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField(); + ConnectionInfo connectInfo = cacheObject.getConnectionInfo(); + if (connectInfo != null) { + AbstractSpan span = ContextManager.createExitSpan(buildOperationName(connectInfo, method.getName(), cacheObject + .getStatementName()), connectInfo.getDatabasePeer()); + Tags.DB_TYPE.set(span, connectInfo.getDBType()); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + String sql = allArguments.length > 0 ? (String) allArguments[0] : ""; + sql = SqlBodyUtil.limitSqlBodySize(sql); + Tags.DB_STATEMENT.set(span, sql); + span.setComponent(connectInfo.getComponent()); + SpanLayer.asDB(span); + } + } + + @Override + public final Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) { + StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField(); + if (cacheObject.getConnectionInfo() != null) { + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public final void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + StatementEnhanceInfos cacheObject = (StatementEnhanceInfos) objInst.getSkyWalkingDynamicField(); + if (cacheObject.getConnectionInfo() != null) { + ContextManager.activeSpan().log(t); + } + } + + private String buildOperationName(ConnectionInfo connectionInfo, String methodName, String statementName) { + return connectionInfo.getDBType() + "/JDBC/" + statementName + "/" + methodName; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/ConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/ConnectionInstrumentation.java new file mode 100644 index 0000000000..2f7083eca4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/ConnectionInstrumentation.java @@ -0,0 +1,144 @@ +/* + * 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.jdbc.mariadb.v3.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.plugin.jdbc.define.Constants; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class ConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.mariadb.jdbc.Connection"; + private static final String CREATE_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.CreateStatementInterceptor"; + private static final String CREATE_PREPARED_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.CreatePreparedStatementInterceptor"; + private static final String CREATE_CALLABLE_STATEMENT_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.CreateCallableStatementInterceptor"; + private static final String SET_CATALOG_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.SetCatalogInterceptor"; + + @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 getMethodsMatcher() { + return named(Constants.CREATE_STATEMENT_METHOD_NAME); + } + + @Override + public String getMethodsInterceptor() { + return CREATE_STATEMENT_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.PREPARE_STATEMENT_METHOD_NAME); + } + + @Override + public String getMethodsInterceptor() { + return CREATE_PREPARED_STATEMENT_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.PREPARE_CALL_METHOD_NAME); + } + + @Override + public String getMethodsInterceptor() { + return CREATE_CALLABLE_STATEMENT_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(Constants.COMMIT_METHOD_NAME) + .or(named(Constants.ROLLBACK_METHOD_NAME)) + .or(named(Constants.CLOSE_METHOD_NAME)) + .or(named(Constants.RELEASE_SAVE_POINT_METHOD_NAME)); + } + + @Override + public String getMethodsInterceptor() { + return Constants.SERVICE_METHOD_INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("setCatalog"); + } + + @Override + public String getMethodsInterceptor() { + return SET_CATALOG_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + + } + + @Override + protected String[] witnessClasses() { + return new String[]{"org.mariadb.jdbc.Connection"}; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/DriverInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/DriverInstrumentation.java new file mode 100644 index 0000000000..b0a3dba6b0 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/DriverInstrumentation.java @@ -0,0 +1,36 @@ +/* + * 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.jdbc.mariadb.v3.define; + +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; +import org.apache.skywalking.apm.plugin.jdbc.define.AbstractDriverInstrumentation; + +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link DriverInstrumentation} presents that skywalking intercepts {@link org.mariadb.jdbc.Driver}. + */ +public class DriverInstrumentation extends AbstractDriverInstrumentation { + private static final String ENHANCE_CLASS = "org.mariadb.jdbc.Driver"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementIgnoredSetterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementIgnoredSetterInstrumentation.java new file mode 100644 index 0000000000..7e036281fb --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementIgnoredSetterInstrumentation.java @@ -0,0 +1,33 @@ +/* + * 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.jdbc.mariadb.v3.define; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.plugin.jdbc.PSSetterDefinitionOfJDBCInstrumentation; + +public class PreparedStatementIgnoredSetterInstrumentation extends PreparedStatementInstrumentation { + + @Override + public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new PSSetterDefinitionOfJDBCInstrumentation(true) + }; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementInstrumentation.java new file mode 100644 index 0000000000..fced984b0b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementInstrumentation.java @@ -0,0 +1,74 @@ +/* + * 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.jdbc.mariadb.v3.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 org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch.byMultiClassMatch; + +public class PreparedStatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String CLIENT_PREPARED_STATEMENT_CLASS = "org.mariadb.jdbc.ClientPreparedStatement"; + private static final String SERVER_PREPARED_STATEMENT_CLASS = "org.mariadb.jdbc.ServerPreparedStatement"; + private static final String PREPARED_STATEMENT_EXECUTE_METHODS_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.PreparedStatementExecuteMethodsInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return byMultiClassMatch( + CLIENT_PREPARED_STATEMENT_CLASS, + SERVER_PREPARED_STATEMENT_CLASS + ); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("execute") + .or(named("executeQuery")) + .or(named("executeUpdate")); + } + + @Override + public String getMethodsInterceptor() { + return PREPARED_STATEMENT_EXECUTE_METHODS_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementNullSetterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementNullSetterInstrumentation.java new file mode 100644 index 0000000000..30a1865174 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementNullSetterInstrumentation.java @@ -0,0 +1,33 @@ +/* + * 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.jdbc.mariadb.v3.define; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.plugin.jdbc.JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint; + +public class PreparedStatementNullSetterInstrumentation extends PreparedStatementInstrumentation { + + @Override + public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new JDBCPreparedStatementNullSetterInstanceMethodsInterceptPoint() + }; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementSetterInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementSetterInstrumentation.java new file mode 100644 index 0000000000..bc625974eb --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/PreparedStatementSetterInstrumentation.java @@ -0,0 +1,33 @@ +/* + * 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.jdbc.mariadb.v3.define; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.plugin.jdbc.PSSetterDefinitionOfJDBCInstrumentation; + +public class PreparedStatementSetterInstrumentation extends PreparedStatementInstrumentation { + + @Override + public final InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new PSSetterDefinitionOfJDBCInstrumentation(false) + }; + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/StatementInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/StatementInstrumentation.java new file mode 100644 index 0000000000..13a8c7e033 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/define/StatementInstrumentation.java @@ -0,0 +1,71 @@ +/* + * 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.jdbc.mariadb.v3.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 org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class StatementInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String MARIADB_STATEMENT_CLASS_NAME = "org.mariadb.jdbc.Statement"; + private static final String STATEMENT_EXECUTE_METHODS_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.StatementExecuteMethodsInterceptor"; + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("execute") + .or(named("executeQuery")) + .or(named("executeUpdate")) + .or(named("executeLargeUpdate")) + .or(named("executeBatch")) + .or(named("executeLargeBatch")); + } + + @Override + public String getMethodsInterceptor() { + return STATEMENT_EXECUTE_METHODS_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return byName(MARIADB_STATEMENT_CLASS_NAME); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..d1bdb703d4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,23 @@ +# 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. + +mariadb-3.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.define.DriverInstrumentation +mariadb-3.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.define.ConnectionInstrumentation +mariadb-3.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.define.StatementInstrumentation +mariadb-3.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.define.PreparedStatementInstrumentation +mariadb-3.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.define.PreparedStatementSetterInstrumentation +mariadb-3.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.define.PreparedStatementNullSetterInstrumentation +mariadb-3.x=org.apache.skywalking.apm.plugin.jdbc.mariadb.v3.define.PreparedStatementIgnoredSetterInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateCallableStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateCallableStatementInterceptorTest.java new file mode 100644 index 0000000000..a034865659 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateCallableStatementInterceptorTest.java @@ -0,0 +1,67 @@ +/* + * 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.jdbc.mariadb.v3; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CreateCallableStatementInterceptorTest { + + private static final String SQL = "Select * from test"; + + private CreateCallableStatementInterceptor interceptor; + + @Mock + private EnhancedInstance ret; + + @Mock + private EnhancedInstance objectInstance; + + @Mock + private ConnectionInfo connectionInfo; + + @Before + public void setUp() { + interceptor = new CreateCallableStatementInterceptor(); + + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo); + } + + @Test + public void testResultIsEnhanceInstance() { + interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, ret); + verify(ret).setSkyWalkingDynamicField(any()); + } + + @Test + public void testResultIsNotEnhanceInstance() { + interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, new Object()); + verify(ret, times(0)).setSkyWalkingDynamicField(any()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreatePreparedStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreatePreparedStatementInterceptorTest.java new file mode 100644 index 0000000000..0c2c51c9ad --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreatePreparedStatementInterceptorTest.java @@ -0,0 +1,67 @@ +/* + * 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.jdbc.mariadb.v3; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CreatePreparedStatementInterceptorTest { + + private static final String SQL = "Select * from test"; + + private CreatePreparedStatementInterceptor interceptor; + + @Mock + private EnhancedInstance ret; + + @Mock + private EnhancedInstance objectInstance; + + @Mock + private ConnectionInfo connectionInfo; + + @Before + public void setUp() { + interceptor = new CreatePreparedStatementInterceptor(); + + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo); + } + + @Test + public void testResultIsEnhanceInstance() { + interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, ret); + verify(ret).setSkyWalkingDynamicField(any()); + } + + @Test + public void testResultIsNotEnhanceInstance() { + interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, new Object()); + verify(ret, times(0)).setSkyWalkingDynamicField(any()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateStatementInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateStatementInterceptorTest.java new file mode 100644 index 0000000000..663ce62d32 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/CreateStatementInterceptorTest.java @@ -0,0 +1,67 @@ +/* + * 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.jdbc.mariadb.v3; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class CreateStatementInterceptorTest { + + private static final String SQL = "Select * from test"; + + private CreateStatementInterceptor interceptor; + + @Mock + private EnhancedInstance ret; + + @Mock + private EnhancedInstance objectInstance; + + @Mock + private ConnectionInfo connectionInfo; + + @Before + public void setUp() { + interceptor = new CreateStatementInterceptor(); + + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(connectionInfo); + } + + @Test + public void testResultIsEnhanceInstance() { + interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, ret); + verify(ret).setSkyWalkingDynamicField(any()); + } + + @Test + public void testResultIsNotEnhanceInstance() { + interceptor.afterMethod(objectInstance, null, new Object[]{SQL}, null, new Object()); + verify(ret, times(0)).setSkyWalkingDynamicField(any()); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/PreparedStatementExecuteMethodsInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/PreparedStatementExecuteMethodsInterceptorTest.java new file mode 100644 index 0000000000..3e624d7952 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/PreparedStatementExecuteMethodsInterceptorTest.java @@ -0,0 +1,153 @@ +/* + * 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.jdbc.mariadb.v3; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.when; +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.JDBCPluginConfig; +import org.apache.skywalking.apm.plugin.jdbc.JDBCPreparedStatementSetterInterceptor; +import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@RunWith(TracingSegmentRunner.class) +public class PreparedStatementExecuteMethodsInterceptorTest { + + private static final String SQL = "Select * from test where id = ?"; + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + private PreparedStatementExecuteMethodsInterceptor serviceMethodInterceptor; + + private JDBCPreparedStatementSetterInterceptor preparedStatementSetterInterceptor; + + @Mock + private ConnectionInfo connectionInfo; + @Mock + private EnhancedInstance objectInstance; + @Mock + private Method method; + private StatementEnhanceInfos enhanceRequireCacheObject; + + @Before + public void setUp() { + JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS = true; + preparedStatementSetterInterceptor = new JDBCPreparedStatementSetterInterceptor(); + serviceMethodInterceptor = new PreparedStatementExecuteMethodsInterceptor(); + + enhanceRequireCacheObject = new StatementEnhanceInfos(connectionInfo, SQL, "PreparedStatement"); + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(enhanceRequireCacheObject); + when(method.getName()).thenReturn("executeQuery"); + when(connectionInfo.getComponent()).thenReturn(ComponentsDefine.MARIADB_JDBC); + when(connectionInfo.getDBType()).thenReturn("Mariadb"); + when(connectionInfo.getDatabaseName()).thenReturn("test"); + when(connectionInfo.getDatabasePeer()).thenReturn("localhost:3306"); + } + + @After + public void clean() { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 2048; + JDBCPluginConfig.Plugin.JDBC.TRACE_SQL_PARAMETERS = false; + } + + @Test + public void testExecutePreparedStatement() throws Throwable { + preparedStatementSetterInterceptor.beforeMethod( + objectInstance, method, new Object[] { + 1, + "abcd" + }, null, null); + preparedStatementSetterInterceptor.beforeMethod( + objectInstance, method, new Object[] { + 2, + "efgh" + }, null, null); + + serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[] {SQL}, null, null); + serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[] {SQL}, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment segment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(segment).size(), is(1)); + AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0); + SpanAssert.assertLayer(span, SpanLayer.DB); + assertThat(span.getOperationName(), is("Mariadb/JDBC/PreparedStatement/executeQuery")); + SpanAssert.assertTag(span, 0, "Mariadb"); + SpanAssert.assertTag(span, 1, "test"); + SpanAssert.assertTag(span, 2, SQL); + SpanAssert.assertTag(span, 3, "[abcd,efgh]"); + } + + @Test + public void testExecutePreparedStatementWithLimitSqlBody() throws Throwable { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 10; + + preparedStatementSetterInterceptor.beforeMethod( + objectInstance, method, new Object[] { + 1, + "abcd" + }, null, null); + preparedStatementSetterInterceptor.beforeMethod( + objectInstance, method, new Object[] { + 2, + "efgh" + }, null, null); + + serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[] {SQL}, null, null); + serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[] {SQL}, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment segment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(segment).size(), is(1)); + AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0); + SpanAssert.assertLayer(span, SpanLayer.DB); + assertThat(span.getOperationName(), is("Mariadb/JDBC/PreparedStatement/executeQuery")); + SpanAssert.assertTag(span, 0, "Mariadb"); + SpanAssert.assertTag(span, 1, "test"); + SpanAssert.assertTag(span, 2, "Select * f..."); + SpanAssert.assertTag(span, 3, "[abcd,efgh]"); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/StatementExecuteMethodsInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/StatementExecuteMethodsInterceptorTest.java new file mode 100644 index 0000000000..ce2e83c69a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mariadb-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/mariadb/v3/StatementExecuteMethodsInterceptorTest.java @@ -0,0 +1,118 @@ +/* + * 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.jdbc.mariadb.v3; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.when; +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.JDBCPluginConfig; +import org.apache.skywalking.apm.plugin.jdbc.define.StatementEnhanceInfos; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +@RunWith(TracingSegmentRunner.class) +public class StatementExecuteMethodsInterceptorTest { + + private static final String SQL = "Select * from test"; + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @Rule + public MockitoRule rule = MockitoJUnit.rule(); + + private StatementExecuteMethodsInterceptor serviceMethodInterceptor; + + @Mock + private ConnectionInfo connectionInfo; + @Mock + private EnhancedInstance objectInstance; + @Mock + private Method method; + private StatementEnhanceInfos enhanceRequireCacheObject; + + @Before + public void setUp() { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 2048; + + serviceMethodInterceptor = new StatementExecuteMethodsInterceptor(); + + enhanceRequireCacheObject = new StatementEnhanceInfos(connectionInfo, SQL, "CallableStatement"); + when(objectInstance.getSkyWalkingDynamicField()).thenReturn(enhanceRequireCacheObject); + when(method.getName()).thenReturn("executeQuery"); + when(connectionInfo.getComponent()).thenReturn(ComponentsDefine.MARIADB_JDBC); + when(connectionInfo.getDBType()).thenReturn("Mariadb"); + when(connectionInfo.getDatabaseName()).thenReturn("test"); + when(connectionInfo.getDatabasePeer()).thenReturn("localhost:3306"); + } + + @Test + public void testExecuteStatement() { + serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[]{SQL}, null, null); + serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[]{SQL}, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment segment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(segment).size(), is(1)); + AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0); + SpanAssert.assertLayer(span, SpanLayer.DB); + assertThat(span.getOperationName(), is("Mariadb/JDBC/CallableStatement/executeQuery")); + SpanAssert.assertTag(span, 0, "Mariadb"); + SpanAssert.assertTag(span, 1, "test"); + SpanAssert.assertTag(span, 2, SQL); + } + + @Test + public void testExecuteStatementWithLimitSqlBody() { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 10; + serviceMethodInterceptor.beforeMethod(objectInstance, method, new Object[]{SQL}, null, null); + serviceMethodInterceptor.afterMethod(objectInstance, method, new Object[]{SQL}, null, null); + + assertThat(segmentStorage.getTraceSegments().size(), is(1)); + TraceSegment segment = segmentStorage.getTraceSegments().get(0); + assertThat(SegmentHelper.getSpans(segment).size(), is(1)); + AbstractTracingSpan span = SegmentHelper.getSpans(segment).get(0); + SpanAssert.assertLayer(span, SpanLayer.DB); + assertThat(span.getOperationName(), is("Mariadb/JDBC/CallableStatement/executeQuery")); + SpanAssert.assertTag(span, 0, "Mariadb"); + SpanAssert.assertTag(span, 1, "test"); + SpanAssert.assertTag(span, 2, "Select * f..."); + } + +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoRemotePeerHelper.java b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoRemotePeerHelper.java index 1dcdb288f8..8fec2f8f4b 100644 --- a/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoRemotePeerHelper.java +++ b/apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoRemotePeerHelper.java @@ -35,7 +35,7 @@ private MongoRemotePeerHelper() { */ public static String getRemotePeer(Cluster cluster) { StringBuilder peersBuilder = new StringBuilder(); - for (ServerDescription description : cluster.getDescription().getServerDescriptions()) { + for (ServerDescription description : cluster.getCurrentDescription().getServerDescriptions()) { ServerAddress address = description.getAddress(); peersBuilder.append(address.getHost()).append(":").append(address.getPort()).append(";"); } diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 1c792ed425..fca054b6a5 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -92,6 +92,7 @@ finagle-6.25.x-plugin quasar-plugin mariadb-2.x-plugin + mariadb-3.x-plugin influxdb-2.x-plugin baidu-brpc-plugin baidu-brpc-3.x-plugin 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 3764ae9716..a829e1a174 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -64,6 +64,7 @@ - lettuce-6.5.x - light4j - mariadb-2.x +- mariadb-3.x - micrometer-1.10.x - memcache-2.x - mongodb-2.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index bbc7da6940..a875618a02 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -28,7 +28,7 @@ metrics based on the tracing data. * [Netty HTTP](https://github.com/netty/netty) 4.1.x (Optional²) * [Solon](https://github.com/opensolon/solon) 2.7.x -> 2.8.x * HTTP Client - * [Feign](https://github.com/OpenFeign/feign) 9.x -> 12.1 + * [Feign](https://github.com/OpenFeign/feign) 9.x -> 13.5 * [Netflix Spring Cloud Feign](https://github.com/spring-cloud/spring-cloud-openfeign) 1.1.x -> 2.x * [Okhttp](https://github.com/square/okhttp) 2.x -> 3.x -> 4.x * [Apache httpcomponent HttpClient](http://hc.apache.org/) 2.0 -> 3.1, 4.2, 4.3, 5.0, 5.1 @@ -50,7 +50,7 @@ metrics based on the tracing data. * H2 Driver 1.3.x -> 1.4.x * [ShardingSphere](https://github.com/apache/shardingsphere) 3.0.0, 4.0.0, 4.0.1, 4.1.0, 4.1.1, 5.0.0 * PostgreSQL Driver 8.x, 9.x, 42.x - * Mariadb Driver 1.8, 2.x (2.0 -> 2.7) + * Mariadb Driver 1.8, 2.x (2.0 -> 2.7), 3.x (3.0 -> 3.5) * [InfluxDB](https://github.com/influxdata/influxdb-java) 2.5 -> 2.17 * [Mssql-Jtds](https://github.com/milesibastos/jTDS) 1.x * [Mssql-jdbc](https://github.com/microsoft/mssql-jdbc) 6.x -> 8.x @@ -91,7 +91,7 @@ metrics based on the tracing data. * [Jedis](https://github.com/xetorthio/jedis) 2.x-4.x * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 3.5.0 -> 3.30.0 * [Lettuce](https://github.com/lettuce-io/lettuce-core) 5.x -> 6.7.1 - * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14, 3.4.0-3.12.7, 4.0.0-4.10.2 + * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14, 3.4.0-3.12.7, 4.0.0-4.11.5 * Memcached Client * [Spymemcached](https://github.com/couchbase/spymemcached) 2.x * [Xmemcached](https://github.com/killme2008/xmemcached) 2.x diff --git a/test/plugin/scenarios/feign-scenario/support-version.list b/test/plugin/scenarios/feign-scenario/support-version.list index eb3667e110..60e6621427 100644 --- a/test/plugin/scenarios/feign-scenario/support-version.list +++ b/test/plugin/scenarios/feign-scenario/support-version.list @@ -23,3 +23,5 @@ 10.12 11.10 12.1 +12.5 +13.5 diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/bin/startup.sh b/test/plugin/scenarios/mariadb-3.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..a7a67d27ab --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-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/mariadb-3.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/mariadb-3.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..9f2a81315d --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/config/expectedData.yaml @@ -0,0 +1,114 @@ +# 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: mariadb-3.x-scenario + segmentSize: ge 1 + segments: + - segmentId: not null + spans: + - operationName: Mariadb/JDBC/Statement/execute + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 87 + isError: false + spanType: Exit + peer: mariadb-server:3306 + skipAnalysis: 'false' + tags: + - {key: db.type, value: Mariadb} + - {key: db.instance, value: test} + - key: db.statement + value: "CREATE TABLE test_table(\nid VARCHAR(1) PRIMARY KEY, \nvalue VARCHAR(10)\ + \ NOT NULL)" + - operationName: Mariadb/JDBC/PreparedStatement/execute + parentSpanId: 0 + spanId: 2 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 87 + isError: false + spanType: Exit + peer: mariadb-server:3306 + skipAnalysis: 'false' + tags: + - {key: db.type, value: Mariadb} + - {key: db.instance, value: test} + - {key: db.statement, value: "INSERT INTO test_table(id, value) VALUES(?,?)"} + - operationName: Mariadb/JDBC/PreparedStatement/execute + parentSpanId: 0 + spanId: 3 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 87 + isError: false + spanType: Exit + peer: mariadb-server:3306 + skipAnalysis: 'false' + tags: + - {key: db.type, value: Mariadb} + - {key: db.instance, value: test} + - {key: db.statement, value: "SELECT id, value FROM test_table WHERE id = ?"} + - operationName: Mariadb/JDBC/Statement/execute + parentSpanId: 0 + spanId: 4 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 87 + isError: false + spanType: Exit + peer: mariadb-server:3306 + skipAnalysis: 'false' + tags: + - {key: db.type, value: Mariadb} + - {key: db.instance, value: test} + - {key: db.statement, value: "DROP table test_table"} + - operationName: Mariadb/JDBC/Connection/close + parentSpanId: 0 + spanId: 5 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 87 + isError: false + spanType: Exit + peer: mariadb-server:3306 + skipAnalysis: 'false' + tags: + - {key: db.type, value: Mariadb} + - {key: db.instance, value: test} + - {key: db.statement, value: ''} + - operationName: GET:/mariadb-3.x-scenario/case/mariadb-scenario + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + spanLayer: Http + isError: false + spanType: Entry + peer: '' + componentId: 1 + tags: + - {key: url, value: 'http://localhost:8080/mariadb-3.x-scenario/case/mariadb-scenario'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + logs: [] + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/configuration.yml b/test/plugin/scenarios/mariadb-3.x-scenario/configuration.yml new file mode 100644 index 0000000000..cebb701abb --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/configuration.yml @@ -0,0 +1,32 @@ +# 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/mariadb-3.x-scenario/case/mariadb-scenario +healthCheck: http://localhost:8080/mariadb-3.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: +depends_on: + - mariadb-server +dependencies: + mariadb-server: + image: mariadb:10.5.2 + hostname: mariadb-server + expose: + - "3306" + environment: + - MYSQL_ROOT_PASSWORD=root + - MYSQL_DATABASE=test diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/pom.xml b/test/plugin/scenarios/mariadb-3.x-scenario/pom.xml new file mode 100644 index 0000000000..b8c31cd066 --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/pom.xml @@ -0,0 +1,123 @@ + + + + + org.apache.skywalking.apm.testcase + mariadb-3.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + + 3.5.1 + ${test.framework.version} + + 2.1.6.RELEASE + + + skywalking-mariadb-3.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + org.mariadb.jdbc + mariadb-java-client + ${test.framework.version} + + + + + mariadb-3.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${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/mariadb-3.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..80cf6eba69 --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/mariadb-3.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/Application.java b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/Application.java new file mode 100644 index 0000000000..ad8ed130c2 --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/Application.java @@ -0,0 +1,39 @@ +/* + * 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.testcase.mariadb; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + private static final Logger LOGGER = LogManager.getLogger(Application.class); + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception ex) { + LOGGER.error("Application start error", ex); + throw ex; + } + } +} diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/MariadbConfig.java b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/MariadbConfig.java new file mode 100644 index 0000000000..7eb8a6b1cb --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/MariadbConfig.java @@ -0,0 +1,58 @@ +/* + * 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.testcase.mariadb; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class MariadbConfig { + private static final Logger LOGGER = LogManager.getLogger(MariadbConfig.class); + private static String URL; + private static String USER_NAME; + private static String PASSWORD; + + static { + InputStream inputStream = MariadbConfig.class.getClassLoader().getResourceAsStream("/jdbc.properties"); + Properties properties = new Properties(); + try { + properties.load(inputStream); + } catch (IOException e) { + LOGGER.error("Failed to load config", e); + } + + URL = properties.getProperty("mariadb.url"); + USER_NAME = properties.getProperty("mariadb.username"); + PASSWORD = properties.getProperty("mariadb.password"); + } + + public static String getUrl() { + return URL; + } + + public static String getUserName() { + return USER_NAME; + } + + public static String getPassword() { + return PASSWORD; + } +} diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/SQLExecutor.java b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/SQLExecutor.java new file mode 100644 index 0000000000..74b7ffbad4 --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/SQLExecutor.java @@ -0,0 +1,70 @@ +/* + * 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.testcase.mariadb; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +public class SQLExecutor implements AutoCloseable { + private static final Logger LOGGER = LogManager.getLogger(SQLExecutor.class); + private Connection connection; + + public SQLExecutor() throws SQLException { + try { + Class.forName("org.mariadb.jdbc.Driver"); + } catch (ClassNotFoundException ex) { + LOGGER.error(ex); + } + connection = DriverManager.getConnection(MariadbConfig.getUrl(), MariadbConfig.getUserName(), MariadbConfig.getPassword()); + } + + public void execute(String sql) throws SQLException { + Statement statement = connection.createStatement(); + statement.execute(sql); + } + + public void insertData(String sql, String id, String value) throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement(sql); + preparedStatement.setString(1, id); + preparedStatement.setString(2, value); + preparedStatement.execute(); + } + + public void queryData(String sql, String id) throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement(sql); + preparedStatement.setString(1, id); + preparedStatement.execute(); + } + + public void closeConnection() throws SQLException { + if (this.connection != null) { + this.connection.close(); + } + } + + @Override + public void close() throws Exception { + closeConnection(); + } +} diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/controller/CaseController.java b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/controller/CaseController.java new file mode 100644 index 0000000000..7f6638bd7d --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mariadb/controller/CaseController.java @@ -0,0 +1,63 @@ +/* + * 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.testcase.mariadb.controller; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.skywalking.apm.testcase.mariadb.SQLExecutor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +public class CaseController { + + private static final Logger LOGGER = LogManager.getLogger(CaseController.class); + + private static final String SUCCESS = "Success"; + + private static final String CREATE_TABLE_SQL = "CREATE TABLE test_table(\n" + "id VARCHAR(1) PRIMARY KEY, \n" + "value VARCHAR(10) NOT NULL)"; + private static final String INSERT_DATA_SQL = "INSERT INTO test_table(id, value) VALUES(?,?)"; + private static final String QUERY_DATA_SQL = "SELECT id, value FROM test_table WHERE id = ?"; + private static final String DELETE_DATA_SQL = "DELETE FROM test_table WHERE id=?"; + private static final String DROP_TABLE_SQL = "DROP table test_table"; + + @RequestMapping("/mariadb-scenario") + @ResponseBody + public String testcase() throws Exception { + try (SQLExecutor sqlExecute = new SQLExecutor()) { + sqlExecute.execute(CREATE_TABLE_SQL); + sqlExecute.insertData(INSERT_DATA_SQL, "1", "value"); + sqlExecute.queryData(QUERY_DATA_SQL, "1"); + sqlExecute.execute(DROP_TABLE_SQL); + } catch (Exception ex) { + LOGGER.error("Failed to execute sql.", ex); + throw ex; + } + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() throws Exception { + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..5045bd899a --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +# +# 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 + servlet: + context-path: /mariadb-3.x-scenario +logging: + config: classpath:log4j2.xml diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/jdbc.properties b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/jdbc.properties new file mode 100644 index 0000000000..4b7d7ad333 --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/jdbc.properties @@ -0,0 +1,18 @@ +# 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. +mariadb.url=jdbc:mariadb://mariadb-server:3306/test +mariadb.username=root +mariadb.password=root diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..b5cda5ae8a --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/test/plugin/scenarios/mariadb-3.x-scenario/support-version.list b/test/plugin/scenarios/mariadb-3.x-scenario/support-version.list new file mode 100644 index 0000000000..de41a47025 --- /dev/null +++ b/test/plugin/scenarios/mariadb-3.x-scenario/support-version.list @@ -0,0 +1,23 @@ +# 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. + +3.0.11 +3.1.4 +3.2.0 +3.3.4 +3.4.1 +3.5.1 + diff --git a/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list b/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list index d48bca9d2d..42c7e89fb5 100644 --- a/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list +++ b/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list @@ -24,4 +24,5 @@ 4.7.2 4.8.2 4.9.1 -4.10.2 \ No newline at end of file +4.10.2 +4.11.5 \ No newline at end of file diff --git a/test/plugin/scenarios/postgresql-above9.4.1207-scenario/support-version.list b/test/plugin/scenarios/postgresql-above9.4.1207-scenario/support-version.list index 99dbebec49..3aa745581d 100644 --- a/test/plugin/scenarios/postgresql-above9.4.1207-scenario/support-version.list +++ b/test/plugin/scenarios/postgresql-above9.4.1207-scenario/support-version.list @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -9.4.1212 42.0.0 42.1.4 42.2.8 From e8795e98eb67fb6587bc64f28c2aa4e619ed7f6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Thu, 9 Apr 2026 20:03:42 +0800 Subject: [PATCH 103/114] Add MongoDB 5.x plugin, Jedis 5.x support, fix Spring MVC javax/jakarta detection (#803) ## Summary - Add MongoDB driver 5.x support (new plugin module for 5.2+, extend 4.x for 5.0-5.1) - Extend Jedis 4.x plugin to support Jedis 5.x (witness method fix) - Fix Spring MVC plugin javax/jakarta servlet detection when both exist on classpath - Document package-private class access pattern for plugins ## MongoDB 5.0-5.1 (4.x plugin extended) Added versions to support-version.list. Same MongoClientDelegate API. ## MongoDB 5.2+ (new mongodb-5.x-plugin module) MongoClusterImpl replaces MongoClientDelegate. New interceptors with remotePeer propagation via setAccessible reflection (MongoClusterImpl is package-private). ## Jedis 5.x (4.x plugin witness fix) All intercepted classes unchanged in 5.x. Plugin was silently not activating because witness Pipeline.persist(1 arg) moved to parent PipeliningBase. Changed witness to Connection.executeCommand(1 arg). Resolves https://github.com/apache/skywalking/issues/11747 ## Spring MVC javax/jakarta fix When both javax.servlet and jakarta.servlet exist on classpath, the exclusive if/else set IS_JAVAX=true and skipped Jakarta check. Fix: check both independently. Ref: https://github.com/apache/skywalking/discussions/13425 --- .claude/skills/new-plugin/SKILL.md | 11 ++ .github/workflows/plugins-test.1.yaml | 1 + .gitignore | 1 + CHANGES.md | 1 + apm-sniffer/apm-sdk-plugin/CLAUDE.md | 19 ++ .../AbstractWitnessInstrumentation.java | 7 +- .../apm-sdk-plugin/mongodb-5.x-plugin/pom.xml | 50 ++++++ .../MongoClusterImplInstrumentation.java | 92 ++++++++++ ...usterOperationExecutorInstrumentation.java | 107 ++++++++++++ ...ongoClusterImplConstructorInterceptor.java | 89 ++++++++++ ...ionExecutorImplConstructorInterceptor.java | 53 ++++++ .../src/main/resources/skywalking-plugin.def | 19 ++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../AbstractMethodInterceptor.java | 20 ++- .../Java-Plugin-Development-Guide.md | 23 +++ .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 4 +- .../jedis-4.x-scenario/support-version.list | 1 + .../mongodb-4.x-scenario/support-version.list | 5 +- .../mongodb-5.x-scenario/bin/startup.sh | 21 +++ .../config/expectedData.yaml | 162 ++++++++++++++++++ .../mongodb-5.x-scenario/configuration.yml | 24 +++ .../scenarios/mongodb-5.x-scenario/pom.xml | 148 ++++++++++++++++ .../src/main/assembly/assembly.xml | 41 +++++ .../apm/testcase/mongodb/Application.java | 34 ++++ .../mongodb/controller/CaseController.java | 95 ++++++++++ .../src/main/resources/application.yaml | 25 +++ .../src/main/resources/log4j2.xml | 30 ++++ .../mongodb-5.x-scenario/support-version.list | 19 ++ 29 files changed, 1090 insertions(+), 14 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterImplInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterOperationExecutorInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/MongoClusterImplConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/OperationExecutorImplConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/Application.java create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/mongodb-5.x-scenario/support-version.list diff --git a/.claude/skills/new-plugin/SKILL.md b/.claude/skills/new-plugin/SKILL.md index 08dc73d0f1..d960d07058 100644 --- a/.claude/skills/new-plugin/SKILL.md +++ b/.claude/skills/new-plugin/SKILL.md @@ -57,6 +57,17 @@ Pick interception points based on these principles: **Principle 1: Data accessibility without reflection.** Choose methods where the information you need (peer address, operation name, request/response details, headers for inject/extract) is directly available as method arguments, return values, or accessible through the `this` object's public API. **Never use reflection to read private fields.** If the data is not accessible at one method, look at a different point in the execution flow. +If the target class is **package-private** (e.g., `final class` without `public`), you cannot import or cast to it. **Same-package helper classes do NOT work** because the agent and application use different classloaders — Java treats them as different runtime packages even with the same package name (`IllegalAccessError`). Use `setAccessible` reflection to call public methods: +```java +try { + java.lang.reflect.Method method = objInst.getClass().getMethod("publicMethodName"); + method.setAccessible(true); // Required for package-private class + Object result = method.invoke(objInst); +} catch (Exception e) { + LOGGER.warn("Failed to access method", e); +} +``` + **Principle 2: Use `EnhancedInstance` dynamic field to propagate context inside the library.** This is the primary mechanism for passing data between interception points. The agent adds a dynamic field to every enhanced class via `EnhancedInstance`. Use it to: - Store server address (peer) at connection/client creation time, retrieve it at command execution time diff --git a/.github/workflows/plugins-test.1.yaml b/.github/workflows/plugins-test.1.yaml index 21d5f04eab..19e20deb5c 100644 --- a/.github/workflows/plugins-test.1.yaml +++ b/.github/workflows/plugins-test.1.yaml @@ -91,6 +91,7 @@ jobs: - lettuce-webflux-5x-scenario - mongodb-3.x-scenario - mongodb-4.x-scenario + - mongodb-5.x-scenario - netty-socketio-scenario - postgresql-above9.4.1207-scenario - mssql-jtds-scenario diff --git a/.gitignore b/.gitignore index e127805e50..da77f29d42 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ packages/ /test/jacoco/classes /test/jacoco/*.exec test/jacoco +.claude/settings.local.json diff --git a/CHANGES.md b/CHANGES.md index bb89a9e688..ad1e3f6c51 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,7 @@ Release Notes. * Extend Spring Kafka plugin to support Spring Kafka 2.4 -> 2.9 and 3.0 -> 3.3. * Enhance test/plugin/run.sh to support extra Maven properties per version in support-version.list (format: version,key=value). * Add MariaDB 3.x plugin (all classes renamed in 3.x). +* Extend Jedis 4.x plugin to support Jedis 5.x (fix witness method for 5.x compatibility). All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/CLAUDE.md b/apm-sniffer/apm-sdk-plugin/CLAUDE.md index eb88c1cbe1..b839fbe73b 100644 --- a/apm-sniffer/apm-sdk-plugin/CLAUDE.md +++ b/apm-sniffer/apm-sdk-plugin/CLAUDE.md @@ -145,6 +145,25 @@ public class MyPluginConfig { ``` Config key becomes: `plugin.myplugin.some_setting` +### Accessing Package-Private Classes + +When a plugin needs to call methods on a **package-private** class in the target library (e.g., `MongoClusterImpl` which is `final class` without `public`), you cannot import or cast to it from the plugin package. + +**Same-package helper classes do NOT work** because the agent and application use different classloaders. Even though the package names match, Java considers them different runtime packages, so package-private access is denied (`IllegalAccessError`). + +**Solution: use `setAccessible` reflection** to call public methods on package-private classes: +```java +try { + java.lang.reflect.Method method = objInst.getClass().getMethod("publicMethodName"); + method.setAccessible(true); // Required for package-private class + Object result = method.invoke(objInst); +} catch (Exception e) { + LOGGER.warn("Failed to access method", e); +} +``` + +**When to use:** Only when the target class is package-private and you need to call its public methods. Prefer normal casting when the class is public. + ### Dependency Management **Plugin dependencies must use `provided` scope:** diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/AbstractWitnessInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/AbstractWitnessInstrumentation.java index 8c736751a3..03e5dc6792 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/AbstractWitnessInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/AbstractWitnessInstrumentation.java @@ -35,8 +35,11 @@ protected String[] witnessClasses() { @Override protected List witnessMethods() { + // Connection.executeCommand(CommandObject) exists in Jedis 4.x+ and 5.x, + // but not in 3.x. Previous witness Pipeline.persist(1) broke in 5.x + // because persist moved from Pipeline to PipeliningBase parent class. return Collections.singletonList(new WitnessMethod( - "redis.clients.jedis.Pipeline", - named("persist").and(takesArguments(1)))); + "redis.clients.jedis.Connection", + named("executeCommand").and(takesArguments(1)))); } } diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/pom.xml new file mode 100644 index 0000000000..141dbd464a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/pom.xml @@ -0,0 +1,50 @@ + + + + + 4.0.0 + + + apm-sdk-plugin + org.apache.skywalking + 9.7.0-SNAPSHOT + + + apm-mongodb-5.x-plugin + jar + + mongodb-5.x-plugin + + + + org.mongodb + mongodb-driver-sync + 5.2.0 + provided + + + org.apache.skywalking + apm-mongodb-4.x-plugin + ${project.version} + provided + + + diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterImplInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterImplInstrumentation.java new file mode 100644 index 0000000000..96b834fbca --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterImplInstrumentation.java @@ -0,0 +1,92 @@ +/* + * 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.mongodb.v5.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 org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * Enhance {@code com.mongodb.client.internal.MongoClusterImpl} which replaces + * {@code MongoClientDelegate} in MongoDB driver 5.2+. + * Extract remotePeer from Cluster (constructor arg[1]) and store in dynamic field. + */ +public class MongoClusterImplInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.mongodb.client.internal.MongoClusterImpl"; + + private static final String CONSTRUCTOR_INTERCEPTOR = + "org.apache.skywalking.apm.plugin.mongodb.v5.interceptor.MongoClusterImplConstructorInterceptor"; + + @Override + protected String[] witnessClasses() { + return new String[] {ENHANCE_CLASS}; + } + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgumentWithType(1, "com.mongodb.internal.connection.Cluster"); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_INTERCEPTOR; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("getOperationExecutor"); + } + + @Override + public String getMethodsInterceptor() { + return CONSTRUCTOR_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterOperationExecutorInstrumentation.java b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterOperationExecutorInstrumentation.java new file mode 100644 index 0000000000..53bdb6da93 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/define/MongoClusterOperationExecutorInstrumentation.java @@ -0,0 +1,107 @@ +/* + * 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.mongodb.v5.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.bytebuddy.ArgumentTypeNameMatch; +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.NameMatch; + +/** + * Enhance {@code MongoClusterImpl$OperationExecutorImpl} in MongoDB driver 5.2+. + *

+ * Constructor interception: propagate remotePeer from enclosing MongoClusterImpl + * (synthetic arg[0] for non-static inner class). + *

+ * Method interception: create exit spans on execute() calls. + * Reuses the 4.x MongoDBOperationExecutorInterceptor. + */ +public class MongoClusterOperationExecutorInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = + "com.mongodb.client.internal.MongoClusterImpl$OperationExecutorImpl"; + + private static final String CONSTRUCTOR_INTERCEPTOR = + "org.apache.skywalking.apm.plugin.mongodb.v5.interceptor.OperationExecutorImplConstructorInterceptor"; + + private static final String EXECUTE_INTERCEPTOR = + "org.apache.skywalking.apm.plugin.mongodb.v4.interceptor.MongoDBOperationExecutorInterceptor"; + + private static final String METHOD_NAME = "execute"; + + private static final String ARGUMENT_TYPE = "com.mongodb.client.ClientSession"; + + @Override + protected String[] witnessClasses() { + return new String[] {"com.mongodb.client.internal.MongoClusterImpl"}; + } + + @Override + protected ClassMatch enhanceClass() { + return NameMatch.byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return ElementMatchers.any(); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_INTERCEPTOR; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return ElementMatchers + .named(METHOD_NAME) + .and(ArgumentTypeNameMatch.takesArgumentWithType(2, ARGUMENT_TYPE)) + .or(ElementMatchers.named(METHOD_NAME) + .and(ArgumentTypeNameMatch.takesArgumentWithType(3, ARGUMENT_TYPE))); + } + + @Override + public String getMethodsInterceptor() { + return EXECUTE_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/MongoClusterImplConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/MongoClusterImplConstructorInterceptor.java new file mode 100644 index 0000000000..242b450c45 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/MongoClusterImplConstructorInterceptor.java @@ -0,0 +1,89 @@ +/* + * 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.mongodb.v5.interceptor; + +import com.mongodb.internal.connection.Cluster; +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.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +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.plugin.mongodb.v4.support.MongoRemotePeerHelper; + +import java.lang.reflect.Method; + +/** + * Intercept {@code MongoClusterImpl} constructor and {@code getOperationExecutor()}. + *

+ * Constructor: extract remotePeer from Cluster (arg[1]) and store in dynamic field. + * getOperationExecutor(): pass remotePeer to the returned OperationExecutor. + */ +public class MongoClusterImplConstructorInterceptor + implements InstanceConstructorInterceptor, InstanceMethodsAroundInterceptor { + + private static final ILog LOGGER = LogManager.getLogger(MongoClusterImplConstructorInterceptor.class); + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + Cluster cluster = (Cluster) allArguments[1]; + String remotePeer = MongoRemotePeerHelper.getRemotePeer(cluster); + objInst.setSkyWalkingDynamicField(remotePeer); + + // The OperationExecutorImpl is created INSIDE this constructor (before onConstruct fires), + // so its constructor interceptor couldn't read the peer yet. Set it now. + // MongoClusterImpl is package-private and loaded by application classloader. + // Same-package helpers from agent classloader cannot access it (different runtime packages). + // Use setAccessible reflection to call getOperationExecutor(). + try { + java.lang.reflect.Method getExecutor = objInst.getClass().getMethod("getOperationExecutor"); + getExecutor.setAccessible(true); + Object executor = getExecutor.invoke(objInst); + if (executor instanceof EnhancedInstance) { + ((EnhancedInstance) executor).setSkyWalkingDynamicField(remotePeer); + } + } catch (Exception e) { + LOGGER.warn("Failed to set remotePeer on OperationExecutor", e); + } + } + + @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 EnhancedInstance) { + EnhancedInstance retInstance = (EnhancedInstance) ret; + String remotePeer = (String) objInst.getSkyWalkingDynamicField(); + if (LOGGER.isDebugEnable()) { + LOGGER.debug("Mark OperationExecutor remotePeer: {}", remotePeer); + } + retInstance.setSkyWalkingDynamicField(remotePeer); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/OperationExecutorImplConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/OperationExecutorImplConstructorInterceptor.java new file mode 100644 index 0000000000..0b7c11862e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v5/interceptor/OperationExecutorImplConstructorInterceptor.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.mongodb.v5.interceptor; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +/** + * Intercept {@code MongoClusterImpl$OperationExecutorImpl} constructor. + * As a non-static inner class, the compiled constructor has the enclosing + * {@code MongoClusterImpl} instance as a synthetic first argument (arg index 0). + * + * Note: This interceptor fires during MongoClusterImpl's constructor, before + * MongoClusterImpl.onConstruct() sets the remotePeer. So the dynamic field + * on the enclosing instance is not yet set. The primary peer propagation + * happens in MongoClusterImplConstructorInterceptor.onConstruct() which + * calls getOperationExecutor() after the constructor completes. + * + * This interceptor serves as a secondary path for OperationExecutorImpl + * instances created later (e.g., via withTimeoutSettings()). + */ +public class OperationExecutorImplConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + for (Object arg : allArguments) { + if (arg instanceof EnhancedInstance) { + EnhancedInstance enclosingInstance = (EnhancedInstance) arg; + String remotePeer = (String) enclosingInstance.getSkyWalkingDynamicField(); + if (remotePeer != null && !remotePeer.isEmpty()) { + objInst.setSkyWalkingDynamicField(remotePeer); + return; + } + } + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..fcd2e7be8f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/mongodb-5.x-plugin/src/main/resources/skywalking-plugin.def @@ -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. + +# MongoDB 5.2+ (MongoClusterImpl replaces MongoClientDelegate) +mongodb-5.x=org.apache.skywalking.apm.plugin.mongodb.v5.define.MongoClusterImplInstrumentation +mongodb-5.x=org.apache.skywalking.apm.plugin.mongodb.v5.define.MongoClusterOperationExecutorInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index fca054b6a5..775ec34e12 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -37,6 +37,7 @@ motan-plugin mongodb-3.x-plugin mongodb-4.x-plugin + mongodb-5.x-plugin feign-default-http-9.x-plugin okhttp-3.x-plugin okhttp-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java index ac51e60b93..67f2709c8f 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java @@ -74,19 +74,21 @@ public abstract class AbstractMethodInterceptor implements InstanceMethodsAround AbstractMethodInterceptor.class.getClassLoader(), JAKARTA_SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD ); + // Check both javax and jakarta independently — both may exist on the classpath. + // For example, a Spring MVC 6.x (Jakarta) app may have javax.servlet as a + // transitive dependency. The runtime request type determines which path is used. try { Class.forName(SERVLET_RESPONSE_CLASS, true, AbstractMethodInterceptor.class.getClassLoader()); - IN_SERVLET_CONTAINER = true; IS_JAVAX = true; + IN_SERVLET_CONTAINER = true; + } catch (Exception ignore) { + } + try { + Class.forName( + JAKARTA_SERVLET_RESPONSE_CLASS, true, AbstractMethodInterceptor.class.getClassLoader()); + IS_JAKARTA = true; + IN_SERVLET_CONTAINER = true; } catch (Exception ignore) { - try { - Class.forName( - JAKARTA_SERVLET_RESPONSE_CLASS, true, AbstractMethodInterceptor.class.getClassLoader()); - IN_SERVLET_CONTAINER = true; - IS_JAKARTA = true; - } catch (Exception ignore2) { - IN_SERVLET_CONTAINER = false; - } } } diff --git a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md index 0498f2011d..201835a1dc 100644 --- a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md +++ b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md @@ -621,3 +621,26 @@ Please follow these steps: 1. Send a pull request and ask for review. 1. The plugin committers will approve your plugins, plugin CI-with-IT, e2e, and the plugin tests will be passed. 1. The plugin is accepted by SkyWalking. + +### Accessing package-private target classes + +When a plugin needs to call methods on a **package-private** class in the target library (e.g., `MongoClusterImpl` which is `final class` without `public`), you cannot import or cast to it from the plugin's `org.apache.skywalking` package. + +**Important:** Same-package helper classes do NOT work because the agent and application use different classloaders. Java treats them as different runtime packages even with identical package names, so package-private access is denied with `IllegalAccessError`. + +**Solution:** Use `setAccessible` reflection to call public methods on package-private classes: + +```java +try { + java.lang.reflect.Method method = objInst.getClass().getMethod("publicMethodName"); + method.setAccessible(true); // Required: class is package-private + Object result = method.invoke(objInst); + if (result instanceof EnhancedInstance) { + ((EnhancedInstance) result).setSkyWalkingDynamicField(value); + } +} catch (Exception e) { + logger.warn("Failed to access method", e); +} +``` + +**When to use:** Only when the target class is package-private and you need to call its public methods. Prefer normal casting in interceptors when the class is public. 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 a829e1a174..2bfd58f872 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -70,6 +70,7 @@ - mongodb-2.x - mongodb-3.x - mongodb-4.x +- mongodb-5.x - motan-0.x - mybatis-3.x - mysql-5.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index a875618a02..772f169c39 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -88,10 +88,10 @@ metrics based on the tracing data. * NoSQL * [aerospike](https://github.com/aerospike/aerospike-client-java) 3.x -> 6.x * Redis - * [Jedis](https://github.com/xetorthio/jedis) 2.x-4.x + * [Jedis](https://github.com/xetorthio/jedis) 2.x-5.x * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 3.5.0 -> 3.30.0 * [Lettuce](https://github.com/lettuce-io/lettuce-core) 5.x -> 6.7.1 - * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14, 3.4.0-3.12.7, 4.0.0-4.11.5 + * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14, 3.4.0-3.12.7, 4.0.0-5.5.x * Memcached Client * [Spymemcached](https://github.com/couchbase/spymemcached) 2.x * [Xmemcached](https://github.com/killme2008/xmemcached) 2.x diff --git a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list b/test/plugin/scenarios/jedis-4.x-scenario/support-version.list index 31258966c3..7545c1ec00 100644 --- a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list +++ b/test/plugin/scenarios/jedis-4.x-scenario/support-version.list @@ -19,3 +19,4 @@ 4.2.3 4.1.1 4.0.1 +5.2.0 diff --git a/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list b/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list index 42c7e89fb5..ec4ce41a71 100644 --- a/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list +++ b/test/plugin/scenarios/mongodb-4.x-scenario/support-version.list @@ -25,4 +25,7 @@ 4.8.2 4.9.1 4.10.2 -4.11.5 \ No newline at end of file +4.11.5 +# 5.0-5.1 still uses MongoClientDelegate (same as 4.x) +5.0.1 +5.1.4 \ No newline at end of file diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/bin/startup.sh b/test/plugin/scenarios/mongodb-5.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..8d9acc35ea --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-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} -Dskywalking.plugin.mongodb.trace_param=true ${home}/../libs/mongodb-5.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/mongodb-5.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..58d2556342 --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-scenario/config/expectedData.yaml @@ -0,0 +1,162 @@ +# 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: mongodb-5.x-scenario + segmentSize: ge 2 + segments: + - segmentId: not null + spans: + - operationName: MongoDB/CreateCollectionOperation + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.bind_vars, value: 'testCollection'} + skipAnalysis: 'false' + - operationName: MongoDB/MixedBulkWriteOperation + parentSpanId: 0 + spanId: 2 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} + - {key: db.bind_vars, value: not null} + skipAnalysis: 'false' + - operationName: MongoDB/FindOperation + parentSpanId: 0 + spanId: 3 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} + - {key: db.bind_vars, value: '{"name": "org"}'} + skipAnalysis: 'false' + - operationName: MongoDB/AggregateOperation + parentSpanId: 0 + spanId: 4 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} + - {key: db.bind_vars, value: '{"$match": {"name": "test"}},'} + skipAnalysis: 'false' + - operationName: MongoDB/MixedBulkWriteOperation + parentSpanId: 0 + spanId: 5 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} + - {key: db.bind_vars, value: '{"name": "org"},'} + skipAnalysis: 'false' + - operationName: MongoDB/FindOperation + parentSpanId: 0 + spanId: 6 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} + - {key: db.bind_vars, value: '{"name": "testA"}'} + skipAnalysis: 'false' + - operationName: MongoDB/MixedBulkWriteOperation + parentSpanId: 0 + spanId: 7 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.collection, value: testCollection} + - {key: db.bind_vars, value: '{"id": "1"},'} + skipAnalysis: 'false' + - operationName: MongoDB/DropDatabaseOperation + parentSpanId: 0 + spanId: 8 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 42 + isError: false + spanType: Exit + peer: mongodb-server:27017 + tags: + - {key: db.type, value: MongoDB} + - {key: db.instance, value: test-database} + - {key: db.bind_vars, value: null} + skipAnalysis: 'false' + - operationName: GET:/mongodb-5.x-scenario/case/mongodb-5.x-scenario + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/mongodb-5.x-scenario/case/mongodb-5.x-scenario'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/configuration.yml b/test/plugin/scenarios/mongodb-5.x-scenario/configuration.yml new file mode 100644 index 0000000000..187a8601a7 --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-scenario/configuration.yml @@ -0,0 +1,24 @@ +# 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/mongodb-5.x-scenario/case/mongodb-5.x-scenario +healthCheck: http://localhost:8080/mongodb-5.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +dependencies: + mongodb-server: + image: mongo:6.0 + hostname: mongodb-server diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/pom.xml b/test/plugin/scenarios/mongodb-5.x-scenario/pom.xml new file mode 100644 index 0000000000..9a0985910c --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-scenario/pom.xml @@ -0,0 +1,148 @@ + + + + + org.apache.skywalking.apm.testcase + mongodb-5.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + 5.2.0 + 2.1.6.RELEASE + 1.18.20 + + + skywalking-mongodb-5.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + org.mongodb + mongodb-driver-core + ${test.framework.version} + + + org.mongodb + mongodb-driver-sync + ${test.framework.version} + + + org.mongodb + bson + ${test.framework.version} + + + + + + + org.mongodb + mongodb-driver-core + + + org.mongodb + mongodb-driver-sync + + + org.mongodb + bson + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + mongodb-5.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..ff39fb806e --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/mongodb-5.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/Application.java b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/Application.java new file mode 100644 index 0000000000..1dd56fec23 --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/Application.java @@ -0,0 +1,34 @@ +/* + * 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.testcase.mongodb; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } +} diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java new file mode 100644 index 0000000000..06a196e216 --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/mongodb/controller/CaseController.java @@ -0,0 +1,95 @@ +/* + * 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.testcase.mongodb.controller; + +import com.mongodb.client.AggregateIterable; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.FindIterable; +import com.mongodb.client.model.Aggregates; +import com.mongodb.client.model.Filters; +import org.bson.BsonDocument; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.List; + +import static com.mongodb.client.model.Filters.eq; + +@RestController +@RequestMapping("/case") +public class CaseController { + + @Value(value = "${mongodb.uri}") + private String connectionString; + + @GetMapping("/healthCheck") + public String health() { + // check connect to mongodb server + try (MongoClient mongoClient = MongoClients.create(connectionString)) { + return "success"; + } + } + + @RequestMapping("/mongodb-5.x-scenario") + public String mongoDBCase() { + try (MongoClient mongoClient = MongoClients.create(connectionString)) { + MongoDatabase db = mongoClient.getDatabase("test-database"); + // CreateCollectionOperation + db.createCollection("testCollection"); + + MongoCollection collection = db.getCollection("testCollection"); + Document document = Document.parse("{id: 1, name: \"test\"}"); + // MixedBulkWriteOperation + collection.insertOne(document); + + // FindOperation + FindIterable findIterable = collection.find(eq("name", "org")); + findIterable.first(); + + // AggregateOperation + List pipeline = Arrays.asList( + Aggregates.match(Filters.eq("name", "test")) + ); + AggregateIterable aggregateIterable = collection.aggregate(pipeline); + aggregateIterable.first(); + + // MixedBulkWriteOperation + collection.updateOne(eq("name", "org"), BsonDocument.parse("{ $set : { \"name\": \"testA\"} }")); + + // FindOperation + findIterable = collection.find(eq("name", "testA")); + findIterable.first(); + + // MixedBulkWriteOperation + collection.deleteOne(eq("id", "1")); + + // DropDatabaseOperation + mongoClient.getDatabase("test-database").drop(); + } + return "success"; + } +} diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..533ff2e37f --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,25 @@ +# +# 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 + servlet: + context-path: /mongodb-5.x-scenario +logging: + config: classpath:log4j2.xml +mongodb: + uri: mongodb://mongodb-server/test \ No newline at end of file diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/mongodb-5.x-scenario/support-version.list b/test/plugin/scenarios/mongodb-5.x-scenario/support-version.list new file mode 100644 index 0000000000..89a4430b05 --- /dev/null +++ b/test/plugin/scenarios/mongodb-5.x-scenario/support-version.list @@ -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. + +# MongoDB 5.2+ (MongoClusterImpl replaces MongoClientDelegate) +5.2.0 +5.5.1 From e732a3222f4a58844c6062a1dfa74f2d871f2835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Fri, 10 Apr 2026 16:03:31 +0800 Subject: [PATCH 104/114] Add Elasticsearch Java client plugin for 7.16.x-9.x (#804) Add Elasticsearch Java client (co.elastic.clients:elasticsearch-java) plugin for 7.16.x-9.x Instrument RestClientTransport and ElasticsearchTransportBase to create ExitSpans for Elasticsearch operations. Captures db.type, db.instance (index name), and db.statement (request DSL) tags, aligned with existing ES plugin conventions. Tested across 26 versions covering every minor from 7.16 to 9.3. --- .github/workflows/plugins-jdk17-test.1.yaml | 1 + .github/workflows/plugins-test.2.yaml | 1 + CHANGES.md | 1 + .../elasticsearch-java-plugin/pom.xml | 48 ++++++ .../java/ElasticsearchPluginConfig.java | 35 +++++ ...ticsearchTransportBaseInstrumentation.java | 81 ++++++++++ .../RestClientTransportInstrumentation.java | 97 ++++++++++++ ...ClientTransportConstructorInterceptor.java | 43 ++++++ .../TransportPerformRequestInterceptor.java | 114 +++++++++++++++ .../src/main/resources/skywalking-plugin.def | 19 +++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 1 + .../bin/startup.sh | 21 +++ .../config/expectedData.yaml | 125 ++++++++++++++++ .../configuration.yml | 34 +++++ .../elasticsearch-java-9.x-scenario/pom.xml | 138 ++++++++++++++++++ .../src/main/assembly/assembly.xml | 41 ++++++ .../testcase/elasticsearch/Application.java | 30 ++++ .../controller/CaseController.java | 96 ++++++++++++ .../src/main/resources/application.yaml | 21 +++ .../src/main/resources/log4j2.xml | 30 ++++ .../support-version.list | 22 +++ .../bin/startup.sh | 21 +++ .../config/expectedData.yaml | 125 ++++++++++++++++ .../configuration.yml | 34 +++++ .../elasticsearch-java-scenario/pom.xml | 138 ++++++++++++++++++ .../src/main/assembly/assembly.xml | 41 ++++++ .../testcase/elasticsearch/Application.java | 29 ++++ .../controller/CaseController.java | 97 ++++++++++++ .../src/main/resources/application.yaml | 21 +++ .../src/main/resources/log4j2.xml | 30 ++++ .../support-version.list | 42 ++++++ 33 files changed, 1579 insertions(+) create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/ElasticsearchPluginConfig.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/define/ElasticsearchTransportBaseInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/define/RestClientTransportInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/interceptor/RestClientTransportConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/interceptor/TransportPerformRequestInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/resources/skywalking-plugin.def create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/Application.java create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/elasticsearch-java-9.x-scenario/support-version.list create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/configuration.yml create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/pom.xml create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/Application.java create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/src/main/resources/application.yaml create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/elasticsearch-java-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index 939393713b..ed6efcfef4 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -81,6 +81,7 @@ jobs: - spring-scheduled-6.x-scenario - caffeine-3.x-scenario - lettuce-webflux-6x-scenario + - elasticsearch-java-9.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/.github/workflows/plugins-test.2.yaml b/.github/workflows/plugins-test.2.yaml index 5fe28c244f..1bbf07ef31 100644 --- a/.github/workflows/plugins-test.2.yaml +++ b/.github/workflows/plugins-test.2.yaml @@ -97,6 +97,7 @@ jobs: - nacos-client-2.x-scenario - rocketmq-scenario - rocketmq-5-grpc-scenario + - elasticsearch-java-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index ad1e3f6c51..237ce9ff0c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,6 +21,7 @@ Release Notes. * Enhance test/plugin/run.sh to support extra Maven properties per version in support-version.list (format: version,key=value). * Add MariaDB 3.x plugin (all classes renamed in 3.x). * Extend Jedis 4.x plugin to support Jedis 5.x (fix witness method for 5.x compatibility). +* Add Elasticsearch Java client (co.elastic.clients:elasticsearch-java) plugin for 7.x-9.x. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/pom.xml new file mode 100644 index 0000000000..0126147e82 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/pom.xml @@ -0,0 +1,48 @@ + + + + + 4.0.0 + + + apm-sdk-plugin + org.apache.skywalking + 9.7.0-SNAPSHOT + + + apm-elasticsearch-java-plugin + jar + + elasticsearch-java-plugin + + + 8.17.0 + + + + + co.elastic.clients + elasticsearch-java + ${elasticsearch-java.version} + provided + + + diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/ElasticsearchPluginConfig.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/ElasticsearchPluginConfig.java new file mode 100644 index 0000000000..c435f439a8 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/ElasticsearchPluginConfig.java @@ -0,0 +1,35 @@ +/* + * 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.elasticsearch.java; + +import org.apache.skywalking.apm.agent.core.boot.PluginConfig; + +public class ElasticsearchPluginConfig { + public static class Plugin { + @PluginConfig(root = ElasticsearchPluginConfig.class) + public static class Elasticsearch { + /** + * If true, trace all the DSL(Domain Specific Language) in ElasticSearch access, default is false + */ + public static boolean TRACE_DSL = false; + + public static int ELASTICSEARCH_DSL_LENGTH_THRESHOLD = 1024; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/define/ElasticsearchTransportBaseInstrumentation.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/define/ElasticsearchTransportBaseInstrumentation.java new file mode 100644 index 0000000000..6ac75f023c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/define/ElasticsearchTransportBaseInstrumentation.java @@ -0,0 +1,81 @@ +/* + * 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.elasticsearch.java.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 org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * Enhance {@code co.elastic.clients.transport.ElasticsearchTransportBase} + * which exists in elasticsearch-java 8.x+. The performRequest method + * moved from RestClientTransport to this base class in 8.x. + *

+ * The peer is propagated from RestClientTransport (subclass) via dynamic field. + */ +public class ElasticsearchTransportBaseInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "co.elastic.clients.transport.ElasticsearchTransportBase"; + + private static final String PERFORM_REQUEST_INTERCEPTOR = + "org.apache.skywalking.apm.plugin.elasticsearch.java.interceptor.TransportPerformRequestInterceptor"; + + @Override + protected String[] witnessClasses() { + return new String[] {ENHANCE_CLASS}; + } + + @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 getMethodsMatcher() { + return named("performRequest"); + } + + @Override + public String getMethodsInterceptor() { + return PERFORM_REQUEST_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/define/RestClientTransportInstrumentation.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/define/RestClientTransportInstrumentation.java new file mode 100644 index 0000000000..e5dacab15f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/define/RestClientTransportInstrumentation.java @@ -0,0 +1,97 @@ +/* + * 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.elasticsearch.java.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 org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * Enhance {@code co.elastic.clients.transport.rest_client.RestClientTransport} + * for the Elasticsearch Java client (co.elastic.clients:elasticsearch-java). + *

+ * Covers both 7.x (performRequest on RestClientTransport) and 8.x+ + * (performRequest inherited from ElasticsearchTransportBase, but constructor on RestClientTransport). + */ +public class RestClientTransportInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "co.elastic.clients.transport.rest_client.RestClientTransport"; + + private static final String CONSTRUCTOR_INTERCEPTOR = + "org.apache.skywalking.apm.plugin.elasticsearch.java.interceptor.RestClientTransportConstructorInterceptor"; + + private static final String PERFORM_REQUEST_INTERCEPTOR = + "org.apache.skywalking.apm.plugin.elasticsearch.java.interceptor.TransportPerformRequestInterceptor"; + + @Override + protected String[] witnessClasses() { + return new String[] {ENHANCE_CLASS}; + } + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgumentWithType(0, "org.elasticsearch.client.RestClient"); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_INTERCEPTOR; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("performRequest"); + } + + @Override + public String getMethodsInterceptor() { + return PERFORM_REQUEST_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/interceptor/RestClientTransportConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/interceptor/RestClientTransportConstructorInterceptor.java new file mode 100644 index 0000000000..e96932ace3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/interceptor/RestClientTransportConstructorInterceptor.java @@ -0,0 +1,43 @@ +/* + * 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.elasticsearch.java.interceptor; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.elasticsearch.client.Node; +import org.elasticsearch.client.RestClient; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Intercept RestClientTransport constructor to extract peer address from RestClient nodes. + */ +public class RestClientTransportConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + RestClient restClient = (RestClient) allArguments[0]; + List nodes = restClient.getNodes(); + String peers = nodes.stream() + .map(node -> node.getHost().toHostString()) + .collect(Collectors.joining(",")); + objInst.setSkyWalkingDynamicField(peers); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/interceptor/TransportPerformRequestInterceptor.java b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/interceptor/TransportPerformRequestInterceptor.java new file mode 100644 index 0000000000..ebf8ec6d41 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/java/org/apache/skywalking/apm/plugin/elasticsearch/java/interceptor/TransportPerformRequestInterceptor.java @@ -0,0 +1,114 @@ +/* + * 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.elasticsearch.java.interceptor; + +import co.elastic.clients.transport.Endpoint; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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 org.apache.skywalking.apm.plugin.elasticsearch.java.ElasticsearchPluginConfig; + +import java.lang.reflect.Method; + +/** + * Intercept ElasticsearchTransport.performRequest() to create exit spans. + *

+ * Args: [0] request, [1] endpoint (Endpoint), [2] options (TransportOptions) + * The endpoint.id() provides the operation name (e.g., "search", "index", "bulk"). + */ +public class TransportPerformRequestInterceptor implements InstanceMethodsAroundInterceptor { + + private static final String DB_TYPE = "Elasticsearch"; + + @Override + @SuppressWarnings("unchecked") + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + Endpoint endpoint = (Endpoint) allArguments[1]; + String operationName = "Elasticsearch/" + endpoint.id(); + + String peers = (String) objInst.getSkyWalkingDynamicField(); + if (peers == null || peers.isEmpty()) { + peers = "Unknown"; + } + + AbstractSpan span = ContextManager.createExitSpan(operationName, peers); + span.setComponent(ComponentsDefine.REST_HIGH_LEVEL_CLIENT); + Tags.DB_TYPE.set(span, DB_TYPE); + SpanLayer.asDB(span); + + Object request = allArguments[0]; + String requestUrl = endpoint.requestUrl(request); + String index = extractIndex(requestUrl); + if (index != null) { + span.tag(Tags.ofKey("db.instance"), index); + } + if (ElasticsearchPluginConfig.Plugin.Elasticsearch.TRACE_DSL) { + String dsl = request.toString(); + if (dsl != null && !dsl.isEmpty()) { + int maxLen = ElasticsearchPluginConfig.Plugin.Elasticsearch.ELASTICSEARCH_DSL_LENGTH_THRESHOLD; + if (maxLen > 0 && dsl.length() > maxLen) { + dsl = dsl.substring(0, maxLen) + "..."; + } + Tags.DB_STATEMENT.set(span, dsl); + } + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + ContextManager.activeSpan().errorOccurred(); + } + + /** + * Extract index name from request URL. + * E.g., "/test-index/_doc/1" → "test-index", "/_bulk" → null + */ + static String extractIndex(String requestUrl) { + if (requestUrl == null || requestUrl.isEmpty()) { + return null; + } + // Remove leading slash + String path = requestUrl.startsWith("/") ? requestUrl.substring(1) : requestUrl; + if (path.isEmpty()) { + return null; + } + // First segment before '/' or '_' prefix means no index + int slashIdx = path.indexOf('/'); + String firstSegment = slashIdx > 0 ? path.substring(0, slashIdx) : path; + if (firstSegment.startsWith("_")) { + return null; + } + return firstSegment; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..b13b674473 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/elasticsearch-java-plugin/src/main/resources/skywalking-plugin.def @@ -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. + +# Elasticsearch Java client (co.elastic.clients:elasticsearch-java) 7.16.x-9.x +elasticsearch-java=org.apache.skywalking.apm.plugin.elasticsearch.java.define.RestClientTransportInstrumentation +elasticsearch-java=org.apache.skywalking.apm.plugin.elasticsearch.java.define.ElasticsearchTransportBaseInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 775ec34e12..5d09bd0957 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -71,6 +71,7 @@ elasticsearch-5.x-plugin elasticsearch-6.x-plugin elasticsearch-7.x-plugin + elasticsearch-java-plugin undertow-plugins rabbitmq-plugin dubbo-conflict-patch 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 2bfd58f872..ed16dc1f85 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -25,6 +25,7 @@ - elasticsearch-5.x - elasticsearch-6.x - elasticsearch-7.x +- elasticsearch-java - fastjson-1.2.x - feign-default-http-9.x - feign-pathvar-9.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 772f169c39..ca6f481f06 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -101,6 +101,7 @@ metrics based on the tracing data. * [transport-client](https://github.com/elastic/elasticsearch/tree/7.0/client/transport) 7.0.0-7.5.2 * [rest-high-level-client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/6.7/index.html) 6.7.1-6.8.4 * [rest-high-level-client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.0/java-rest-high.html) 7.x + * [elasticsearch-java](https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/index.html) 7.17.x-9.x * [Solr](https://github.com/apache/solr/) * [SolrJ](https://github.com/apache/solr/tree/main/solr/solrj) 7.x * [Cassandra](https://github.com/apache/cassandra) 3.x diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/bin/startup.sh b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..e054a8dc76 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-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} -Dskywalking.plugin.elasticsearch.trace_dsl=true ${home}/../libs/elasticsearch-java-9.x-scenario.jar & diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..b9af4b71cc --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/config/expectedData.yaml @@ -0,0 +1,125 @@ +# 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: elasticsearch-java-9.x-scenario + segmentSize: ge 2 + segments: + - segmentId: not null + spans: + - operationName: Elasticsearch/es/indices.create + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/index + parentSpanId: 0 + spanId: 2 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/get + parentSpanId: 0 + spanId: 3 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/search + parentSpanId: 0 + spanId: 4 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/delete + parentSpanId: 0 + spanId: 5 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/indices.delete + parentSpanId: 0 + spanId: 6 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: GET:/elasticsearch-java-case/case/elasticsearch + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + spanLayer: Http + isError: false + spanType: Entry + componentId: 1 + tags: + - {key: url, value: not null} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/configuration.yml b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/configuration.yml new file mode 100644 index 0000000000..f660224a0f --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/configuration.yml @@ -0,0 +1,34 @@ +# 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/elasticsearch-java-case/case/elasticsearch +healthCheck: http://localhost:8080/elasticsearch-java-case/case/healthCheck +startScript: ./bin/startup.sh +environment: +- elasticsearch.server=elasticsearch-server:9200 +dependencies: + elasticsearch-server: + image: docker.elastic.co/elasticsearch/elasticsearch:9.0.0 + hostname: elasticsearch-server + removeOnExit: true + expose: + - 9200 + environment: + - cluster.name=docker-node + - xpack.security.enabled=false + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + - discovery.type=single-node diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/pom.xml b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/pom.xml new file mode 100644 index 0000000000..8ca30a4aa0 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/pom.xml @@ -0,0 +1,138 @@ + + + + + org.apache.skywalking.apm.testcase + elasticsearch-java-9.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 17 + 3.8.1 + + 9.0.0 + + 3.0.13 + + + skywalking-elasticsearch-java-9.x-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + jul-to-slf4j + org.slf4j + + + + + + co.elastic.clients + elasticsearch-java + ${test.framework.version} + + + + org.elasticsearch.client + elasticsearch-rest-client + ${test.framework.version} + + + com.fasterxml.jackson.core + jackson-databind + + + + + elasticsearch-java-9.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..42a1323949 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/elasticsearch-java-9.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/Application.java b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/Application.java new file mode 100644 index 0000000000..3ce49f987a --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/Application.java @@ -0,0 +1,30 @@ +/* + * 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.testcase.elasticsearch; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchClientAutoConfiguration; + +@SpringBootApplication(exclude = ElasticsearchClientAutoConfiguration.class) +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java new file mode 100644 index 0000000000..3f2be16239 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java @@ -0,0 +1,96 @@ +/* + * 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.testcase.elasticsearch.controller; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.IndexResponse; +import co.elastic.clients.elasticsearch.core.GetResponse; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.DeleteResponse; +import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; +import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/elasticsearch-java-case/case") +public class CaseController { + + @Value("${elasticsearch.server}") + private String elasticsearchServer; + + @GetMapping("/healthCheck") + public String healthCheck() throws IOException { + RestClient restClient = RestClient.builder(HttpHost.create(elasticsearchServer)).build(); + RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + ElasticsearchClient client = new ElasticsearchClient(transport); + try { + client.info(); + return "Success"; + } finally { + restClient.close(); + } + } + + @GetMapping("/elasticsearch") + public String elasticsearch() throws IOException { + RestClient restClient = RestClient.builder(HttpHost.create(elasticsearchServer)).build(); + RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + ElasticsearchClient client = new ElasticsearchClient(transport); + try { + + // Create index + CreateIndexResponse createResp = client.indices().create(c -> c.index("test-index")); + + // Index document + Map doc = new HashMap<>(); + doc.put("name", "test"); + doc.put("value", "skywalking"); + IndexResponse indexResp = client.index(i -> i.index("test-index").id("1").document(doc)); + + // Get document + GetResponse getResp = client.get(g -> g.index("test-index").id("1"), Map.class); + + // Search + SearchResponse searchResp = client.search(s -> s + .index("test-index") + .query(q -> q.match(m -> m.field("name").query("test"))), Map.class); + + // Delete document + DeleteResponse deleteResp = client.delete(d -> d.index("test-index").id("1")); + + // Delete index + DeleteIndexResponse deleteIndexResp = client.indices().delete(d -> d.index("test-index")); + + return "Success"; + } finally { + restClient.close(); + } + } +} diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..ba18cc1c03 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,21 @@ +# +# 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 +logging: + config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/elasticsearch-java-9.x-scenario/support-version.list b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/support-version.list new file mode 100644 index 0000000000..2f8cf94b33 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-9.x-scenario/support-version.list @@ -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. + +# co.elastic.clients:elasticsearch-java 9.x (requires JDK 17) +# Versions must match elasticsearch-rest-client available versions +9.0.8 +9.1.10 +9.2.8 +9.3.3 diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/bin/startup.sh b/test/plugin/scenarios/elasticsearch-java-scenario/bin/startup.sh new file mode 100644 index 0000000000..eb5ce9db9e --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-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} -Dskywalking.plugin.elasticsearch.trace_dsl=true ${home}/../libs/elasticsearch-java-scenario.jar & diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/config/expectedData.yaml b/test/plugin/scenarios/elasticsearch-java-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..0d79dbce45 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-scenario/config/expectedData.yaml @@ -0,0 +1,125 @@ +# 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: elasticsearch-java-scenario + segmentSize: ge 2 + segments: + - segmentId: not null + spans: + - operationName: Elasticsearch/es/indices.create + parentSpanId: 0 + spanId: 1 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/index + parentSpanId: 0 + spanId: 2 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/get + parentSpanId: 0 + spanId: 3 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/search + parentSpanId: 0 + spanId: 4 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/delete + parentSpanId: 0 + spanId: 5 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: Elasticsearch/es/indices.delete + parentSpanId: 0 + spanId: 6 + spanLayer: Database + startTime: nq 0 + endTime: nq 0 + componentId: 77 + isError: false + spanType: Exit + peer: not null + skipAnalysis: false + tags: + - {key: db.type, value: Elasticsearch} + - {key: db.instance, value: test-index} + - {key: db.statement, value: not null} + - operationName: GET:/elasticsearch-java-case/case/elasticsearch + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + spanLayer: Http + isError: false + spanType: Entry + componentId: 1 + tags: + - {key: url, value: not null} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/configuration.yml b/test/plugin/scenarios/elasticsearch-java-scenario/configuration.yml new file mode 100644 index 0000000000..a6b201e828 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-scenario/configuration.yml @@ -0,0 +1,34 @@ +# 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/elasticsearch-java-case/case/elasticsearch +healthCheck: http://localhost:8080/elasticsearch-java-case/case/healthCheck +startScript: ./bin/startup.sh +environment: +- elasticsearch.server=elasticsearch-server:9200 +dependencies: + elasticsearch-server: + image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0 + hostname: elasticsearch-server + removeOnExit: true + expose: + - 9200 + environment: + - cluster.name=docker-node + - xpack.security.enabled=false + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + - discovery.type=single-node diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/pom.xml b/test/plugin/scenarios/elasticsearch-java-scenario/pom.xml new file mode 100644 index 0000000000..275b963cd2 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-scenario/pom.xml @@ -0,0 +1,138 @@ + + + + + org.apache.skywalking.apm.testcase + elasticsearch-java-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + + 8.12.0 + + 2.1.6.RELEASE + + + skywalking-elasticsearch-java-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + jul-to-slf4j + org.slf4j + + + + + + co.elastic.clients + elasticsearch-java + ${test.framework.version} + + + + org.elasticsearch.client + elasticsearch-rest-client + ${test.framework.version} + + + com.fasterxml.jackson.core + jackson-databind + + + + + elasticsearch-java-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..20d778c34c --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/elasticsearch-java-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/Application.java b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/Application.java new file mode 100644 index 0000000000..2cf2b3e563 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/Application.java @@ -0,0 +1,29 @@ +/* + * 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.testcase.elasticsearch; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java new file mode 100644 index 0000000000..66180bfcd9 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/java/org/apache/skywalking/apm/testcase/elasticsearch/controller/CaseController.java @@ -0,0 +1,97 @@ +/* + * 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.testcase.elasticsearch.controller; + +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch.core.IndexResponse; +import co.elastic.clients.elasticsearch.core.GetResponse; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.DeleteResponse; +import co.elastic.clients.elasticsearch.indices.CreateIndexResponse; +import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse; +import co.elastic.clients.elasticsearch._types.FieldValue; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/elasticsearch-java-case/case") +public class CaseController { + + @Value("${elasticsearch.server}") + private String elasticsearchServer; + + @GetMapping("/healthCheck") + public String healthCheck() throws IOException { + RestClient restClient = RestClient.builder(HttpHost.create(elasticsearchServer)).build(); + RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + ElasticsearchClient client = new ElasticsearchClient(transport); + try { + client.info(); + return "Success"; + } finally { + restClient.close(); + } + } + + @GetMapping("/elasticsearch") + public String elasticsearch() throws IOException { + RestClient restClient = RestClient.builder(HttpHost.create(elasticsearchServer)).build(); + RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + ElasticsearchClient client = new ElasticsearchClient(transport); + try { + + // Create index + CreateIndexResponse createResp = client.indices().create(c -> c.index("test-index")); + + // Index document + Map doc = new HashMap<>(); + doc.put("name", "test"); + doc.put("value", "skywalking"); + IndexResponse indexResp = client.index(i -> i.index("test-index").id("1").document(doc)); + + // Get document + GetResponse getResp = client.get(g -> g.index("test-index").id("1"), Map.class); + + // Search + SearchResponse searchResp = client.search(s -> s + .index("test-index") + .query(q -> q.match(m -> m.field("name").query(FieldValue.of("test")))), Map.class); + + // Delete document + DeleteResponse deleteResp = client.delete(d -> d.index("test-index").id("1")); + + // Delete index + DeleteIndexResponse deleteIndexResp = client.indices().delete(d -> d.index("test-index")); + + return "Success"; + } finally { + restClient.close(); + } + } +} diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..ba18cc1c03 --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/resources/application.yaml @@ -0,0 +1,21 @@ +# +# 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 +logging: + config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/elasticsearch-java-scenario/support-version.list b/test/plugin/scenarios/elasticsearch-java-scenario/support-version.list new file mode 100644 index 0000000000..114e16d1bf --- /dev/null +++ b/test/plugin/scenarios/elasticsearch-java-scenario/support-version.list @@ -0,0 +1,42 @@ +# 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. + +# co.elastic.clients:elasticsearch-java +# ES server fixed at 8.17.0 (backward compatible with 7.x/8.x clients) +# 7.16+: co.elastic.clients.transport.rest_client.RestClientTransport +# 8.x: ElasticsearchTransportBase.performRequest +7.16.3 +7.17.29 +8.0.1 +8.1.3 +8.2.3 +8.3.3 +8.4.3 +8.5.3 +8.6.2 +8.7.1 +8.8.2 +8.9.2 +8.10.4 +8.11.4 +8.12.2 +8.13.4 +8.14.3 +8.15.5 +8.16.6 +8.17.10 +8.18.8 +8.19.14 From 709dfef191574faff371144a90489fdd3c050430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Sat, 11 Apr 2026 09:31:54 +0800 Subject: [PATCH 105/114] Only publish toolkit to Maven Central, add unified release script (#805) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Set maven.deploy.skip=true by default, override to false only in。apm-application-toolkit. Agent and plugins are distributed via download package and Docker images, not Maven Central. - Add tools/releasing/release.sh with two-step release flow: prepare-vote (preflight + prepare + stage + upload + vote email) vote-passed (promote + docker + announce email + cleanup). - Remove create_release.sh (logic merged into release.sh stage). - Update release-java-agent.md documentation. --- CHANGES.md | 4 +- apm-application-toolkit/pom.xml | 5 + docs/en/contribution/release-java-agent.md | 254 ++------ pom.xml | 2 + tools/releasing/create_release.sh | 84 --- tools/releasing/release.sh | 648 +++++++++++++++++++++ 6 files changed, 692 insertions(+), 305 deletions(-) delete mode 100755 tools/releasing/create_release.sh create mode 100755 tools/releasing/release.sh diff --git a/CHANGES.md b/CHANGES.md index 237ce9ff0c..ef6a81a3e4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,7 +21,9 @@ Release Notes. * Enhance test/plugin/run.sh to support extra Maven properties per version in support-version.list (format: version,key=value). * Add MariaDB 3.x plugin (all classes renamed in 3.x). * Extend Jedis 4.x plugin to support Jedis 5.x (fix witness method for 5.x compatibility). -* Add Elasticsearch Java client (co.elastic.clients:elasticsearch-java) plugin for 7.x-9.x. +* Add Elasticsearch Java client (co.elastic.clients:elasticsearch-java) plugin for 7.16.x-9.x. +* Only publish `apm-application-toolkit` modules to Maven Central. Agent and plugins are distributed via download package and Docker images. +* Add unified release script (`tools/releasing/release.sh`) with two-step flow: `prepare-vote` and `vote-passed`. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-application-toolkit/pom.xml b/apm-application-toolkit/pom.xml index cc173543d0..b018a7ef16 100644 --- a/apm-application-toolkit/pom.xml +++ b/apm-application-toolkit/pom.xml @@ -26,6 +26,11 @@ apm-application-toolkit pom + + + false + + apm-toolkit-log4j-1.x apm-toolkit-log4j-2.x diff --git a/docs/en/contribution/release-java-agent.md b/docs/en/contribution/release-java-agent.md index 567cf81615..5b941a822c 100644 --- a/docs/en/contribution/release-java-agent.md +++ b/docs/en/contribution/release-java-agent.md @@ -36,151 +36,47 @@ If you are a committer, use your Apache ID and password to log in this svn, and 1. Upload your GPG public key to the public GPG site, such as [MIT's site](http://pgp.mit.edu:11371/). This site should be in the Apache maven staging repository checklist. -## Test your settings -This step is only for testing purpose. If your env is correctly set, you don't need to check every time. -``` -./mvnw clean install(this will build artifacts, sources and sign) -``` - -## Prepare for the release -``` -./mvnw release:clean -./mvnw release:prepare -DautoVersionSubmodules=true -Pall -``` - -- Set version number as x.y.z, and tag as **v**x.y.z (The version tag must start with **v**. You will find out why this is necessary in the next step.) - -_You could do a GPG signature before preparing for the release. If you need to input the password to sign, and the maven doesn't provide you with the opportunity to do so, this may lead to failure of the release. To resolve this, you may run `gpg --sign xxx` in any file. This will allow it to remember the password for long enough to prepare for the release._ - -## Stage the release -``` -./mvnw release:perform -DskipTests -Pall -``` +## Release using the release script -- The release will be automatically inserted into a temporary staging repository. +The release script `tools/releasing/release.sh` automates the full release workflow. The release is a **two-step process** with a vote in between. -## Build and sign the source code and binary package +### Quick start ```shell -export RELEASE_VERSION=x.y.z (example: RELEASE_VERSION=5.0.0-alpha) -cd tools/releasing -bash create_release.sh -``` - -This script takes care of the following things: -1. Use `v` + `RELEASE_VERSION` as tag to clone the codes. -2. Complete `git submodule init/update`. -3. Exclude all unnecessary files in the target source tar, such as `.git`, `.github`, and `.gitmodules`. See the script for more details. -4. Execute `gpg` and `shasum 512` for source code tar. -5. Use maven package to build the agent tar. -6. Execute `gpg` and `shasum 512` for binary tar. - -`apache-skywalking-java-agent-x.y.z-src.tgz` and files ending with `.asc` and `.sha512` may be found in the `tools/releasing` folder. -`apache-skywalking-java-agent-x.y.z.tgz` and files ending with `.asc` and `.sha512` may be found in the `tools/releasing/apache-skywalking-java-agent-x.y.z` folder. - - -## Upload to Apache svn -1. Use your Apache ID to log in to `https://dist.apache.org/repos/dist/dev/skywalking/java-agent/`. -1. Create a folder and name it by the release version and round, such as: `x.y.z` -1. Upload the source code package to the folder with files ending with `.asc` and `.sha512`. -1. Upload the distribution package to the folder with files ending with `.asc` and `.sha512`. +# Step 1: Build, stage, upload, and generate vote email +./tools/releasing/release.sh prepare-vote x.y.z -## Make the internal announcements -Send an announcement mail in dev mail list. +# (send vote email to dev@skywalking.apache.org, wait 72h for vote to pass) +# Step 2: Promote, push Docker images, generate announce email, and clean up +./tools/releasing/release.sh vote-passed [old_version_to_remove] ``` -Mail title: [ANNOUNCE] SkyWalking Java Agent x.y.z test build available - -Mail content: -The test build of Java Agent x.y.z is available. - -We welcome any comments you may have, and will take all feedback into -account if a quality vote is called for this build. - -Release notes: - - * https://github.com/apache/skywalking-java/blob/master/changes/changes-x.y.z.md -Release Candidate: +Run `./tools/releasing/release.sh` without arguments to see all available commands, including individual steps if you need to run them separately. - * https://dist.apache.org/repos/dist/dev/skywalking/java-agent/xxxx - * sha512 checksums +### Pre-flight checks +Before starting, the script verifies: +- Required tools are installed (git, gpg, svn, shasum, mvn, java, tar, gh) +- GPG signing works **without password prompt** (critical for maven release) +- Maven settings contain Apache server credentials +- Git working tree is clean -Maven 2 staging repository: - - * https://repository.apache.org/content/repositories/xxxx/org/apache/skywalking-java/ - -Release Tag : - - * (Git Tag) x.y.z - -Release CommitID : - - * https://github.com/apache/skywalking-java/tree/(Git Commit ID) - * Git submodule - * apm-protocol/apm-network/src/main/proto: https://github.com/apache/skywalking-data-collect-protocol/tree/(Git Commit ID) - -Keys to verify the Release Candidate : - - * https://dist.apache.org/repos/dist/release/skywalking/KEYS - -Guide to build the release from source : - - > ./mvnw clean package - -A vote regarding the quality of this test build will be initiated -within the next couple of days. +If GPG signing fails, configure gpg-agent to cache the passphrase: ``` - -## Wait for at least 48 hours for test responses -Any PMC member, committer or contributor can test the release features and provide feedback. -Based on that, the PMC will decide whether to start the voting process. - -## Call a vote in dev -Call a vote in `dev@skywalking.apache.org` - +# ~/.gnupg/gpg-agent.conf +default-cache-ttl 86400 +max-cache-ttl 86400 ``` -Mail title: [VOTE] Release Apache SkyWalking Java Agent version x.y.z - -Mail content: -Hi All, -This is a call for vote to release Apache SkyWalking Java Agent version x.y.z. - -Release notes: - - * https://github.com/apache/skywalking-java/blob/master/changes/changes-x.y.z.md - -Release Candidate: - - * https://dist.apache.org/repos/dist/dev/skywalking/java-agent/xxxx - * sha512 checksums - -Maven 2 staging repository: +Then run `gpgconf --kill gpg-agent` and `gpg --sign /dev/null` to cache it. - * https://repository.apache.org/content/repositories/xxxx/org/apache/skywalking/ +### prepare-vote +`prepare-vote` runs the following steps in sequence: +1. **preflight** — verify tools and environment +2. **prepare** — create `release/x.y.z` branch, run `mvn release:prepare` (creates tag `vx.y.z` with full CHANGES.md), then archive changelog and reset for next version, push branch and tag, create PR +3. **stage** — run `mvn release:perform`, build source and binary tars with GPG signatures and sha512 checksums +4. **upload** — upload to Apache SVN `dist/dev` (prompts for SVN credentials) +5. **email vote** — print vote email template with pre-filled version, commit ID, submodule commit, and checksums -Release Tag : - - * (Git Tag) x.y.z - -Release CommitID : - - * https://github.com/apache/skywalking-java/tree/(Git Commit ID) - * Git submodule - * apm-protocol/apm-network/src/main/proto: https://github.com/apache/skywalking-data-collect-protocol/tree/(Git Commit ID) - -Keys to verify the Release Candidate : - - * https://dist.apache.org/repos/dist/release/skywalking/KEYS - -Guide to build the release from source : - - > ./mvnw clean package - -Voting will start now (xxxx date) and will remain open for at least 72 hours, Request all PMC members to give their vote. -[ ] +1 Release this package. -[ ] +0 No opinion. -[ ] -1 Do not release this package because.... -``` +Copy the generated email and send it to `dev@skywalking.apache.org`. Voting remains open for at least 72 hours. At least 3 (+1 binding) PMC votes with more +1 than -1 are required. ## Vote Check All PMC members and committers should check these before casting +1 votes. @@ -195,91 +91,9 @@ are found in `https://dist.apache.org/repos/dist/dev/skywalking/java-agent/x.y.z 1. Build a distribution package from the source code package (`apache-skywalking-java-agent-x.y.z-src.tar.gz`). 1. Check the Apache License Header. Run `docker run --rm -v $(pwd):/github/workspace apache/skywalking-eyes header check`. (No binaries in source codes) - -The voting process is as follows: -1. All PMC member votes are +1 binding, and all other votes are +1 but non-binding. -1. If you obtain at least 3 (+1 binding) votes with more +1 than -1 votes within 72 hours, the release will be approved. - - -## Publish the release -1. Move source codes tar and distribution packages to `https://dist.apache.org/repos/dist/release/skywalking/java-agent/`. -``` -> export SVN_EDITOR=vim -> svn mv https://dist.apache.org/repos/dist/dev/skywalking/java-agent/x.y.z https://dist.apache.org/repos/dist/release/skywalking/java-agent -.... -enter your apache password -.... - -``` -2. Release in the nexus staging repo. -3. Public download source and distribution tar/zip are located in `http://www.apache.org/dyn/closer.cgi/skywalking/java-agent/x.y.z/xxx`. -The Apache mirror path is the only release information that we publish. -4. Public asc and sha512 are located in `https://www.apache.org/dist/skywalking/java-agent/x.y.z/xxx`. -5. Public KEYS point to `https://www.apache.org/dist/skywalking/KEYS`. -6. Update the website download page. http://skywalking.apache.org/downloads/ . Add a new download source, distribution, sha512, asc, and document -links. The links can be found following rules (3) to (6) above. -7. Add a release event on the website homepage and event page. Announce the public release with changelog or key features. -8. Send ANNOUNCE email to `dev@skywalking.apache.org`, `announce@apache.org`. The sender should use the Apache email account. -``` -Mail title: [ANNOUNCE] Apache SkyWalking Java Agent x.y.z released - -Mail content: -Hi all, - -Apache SkyWalking Team is glad to announce the first release of Apache SkyWalking Java Agent x.y.z. - -SkyWalking: APM (application performance monitor) tool for distributed systems, -especially designed for microservices, cloud native and container-based (Docker, Kubernetes, Mesos) architectures. - -The Java Agent for Apache SkyWalking, which provides the native tracing/metrics/logging abilities for Java projects. - -This release contains a number of new features, bug fixes and improvements compared to -version a.b.c(last release). The notable changes since x.y.z include: - -(Highlight key changes) -1. ... -2. ... -3. ... - -Please refer to the change log for the complete list of changes: -https://github.com/apache/skywalking-java/blob/master/changes/changes-x.y.z.md - -Apache SkyWalking website: -http://skywalking.apache.org/ - -Downloads: -http://skywalking.apache.org/downloads/ - -Twitter: -https://twitter.com/AsfSkyWalking - -SkyWalking Resources: -- GitHub: https://github.com/apache/skywalking-java -- Issue: https://github.com/apache/skywalking/issues -- Mailing list: dev@skywalkiing.apache.org - - -- Apache SkyWalking Team -``` - -## Release Docker images - -```shell -export SW_VERSION=x.y.z -git clone --depth 1 --branch v$SW_VERSION https://github.com/apache/skywalking-java.git -cd skywalking-java - -curl -O https://dist.apache.org/repos/dist/release/skywalking/java-agent/$SW_VERSION/apache-skywalking-java-agent-$SW_VERSION.tgz -tar -xzvf apache-skywalking-java-agent-$SW_VERSION.tgz - -export NAME=skywalking-java-agent -export HUB=apache -export TAG=$SW_VERSION - -make docker.push.alpine docker.push.java8 docker.push.java11 docker.push.java17 docker.push.java21 docker.push.java25 -``` - -## Clean up the old releases -Once the latest release has been published, you should clean up the old releases from the mirror system. -1. Update the download links (source, dist, asc, and sha512) on the website to the archive repo (https://archive.apache.org/dist/skywalking). -2. Remove previous releases from https://dist.apache.org/repos/dist/release/skywalking/java-agent. +## vote-passed +After the vote passes, run `vote-passed` which executes: +1. **promote** — move packages from `dist/dev` to `dist/release` in Apache SVN (prompts for SVN credentials), then release the Nexus staging repository at https://repository.apache.org and update the website download page +2. **docker** — build and push all Docker image variants (alpine, java8, java11, java17, java21, java25) +3. **email announce** — print announcement email template. Copy and send to `dev@skywalking.apache.org` and `announce@apache.org` +4. **cleanup** (optional) — if old version is provided, remove it from `dist/release`. Update download page links to point to `https://archive.apache.org/dist/skywalking` diff --git a/pom.xml b/pom.xml index b675688a4a..1f3297d2d1 100755 --- a/pom.xml +++ b/pom.xml @@ -131,6 +131,8 @@ 1.33 1.5 true + + true 0.46.0 diff --git a/tools/releasing/create_release.sh b/tools/releasing/create_release.sh deleted file mode 100755 index 98cedccc01..0000000000 --- a/tools/releasing/create_release.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env 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. -# - -# This script relies on few environment variables to determine source code package -# behavior, those variables are: -# RELEASE_VERSION -- The version of this source package. -# For example: RELEASE_VERSION=5.0.0-alpha - - -RELEASE_VERSION=${RELEASE_VERSION} -TAG_NAME=v${RELEASE_VERSION} -PRODUCT_NAME="apache-skywalking-java-agent" - -echo "Release version "${RELEASE_VERSION} -echo "Source tag "${TAG_NAME} - -if [ "$RELEASE_VERSION" == "" ]; then - echo "RELEASE_VERSION environment variable not found, Please setting the RELEASE_VERSION." - echo "For example: export RELEASE_VERSION=5.0.0-alpha" - exit 1 -fi - -echo "Creating source package" - -PRODUCT_NAME=${PRODUCT_NAME}-${RELEASE_VERSION} - -rm -rf ${PRODUCT_NAME} -mkdir ${PRODUCT_NAME} - -git clone https://github.com/apache/skywalking-java.git ./${PRODUCT_NAME} -cd ${PRODUCT_NAME} - -TAG_EXIST=`git tag -l ${TAG_NAME} | wc -l` - -if [ ${TAG_EXIST} -ne 1 ]; then - echo "Could not find the tag named" ${TAG_NAME} - exit 1 -fi - -git checkout ${TAG_NAME} - -# Init submodules -git submodule init -git submodule update - -# Generate a static skywalking-agent-version.properties and override the template when releasing source tar -# because after that there is no Git information anymore. -./mvnw -q -pl apm-sniffer/apm-agent-core initialize \ - -DgenerateGitPropertiesFilename="$(pwd)/apm-sniffer/apm-agent-core/src/main/resources/skywalking-agent-version.properties" - -cd .. -# Build source code tar -tar czf ${PRODUCT_NAME}-src.tgz \ - --exclude .git \ - --exclude .DS_Store \ - --exclude .github \ - --exclude .gitignore \ - --exclude .gitmodules \ - ${PRODUCT_NAME} - -gpg --armor --detach-sig ${PRODUCT_NAME}-src.tgz - -shasum -a 512 ${PRODUCT_NAME}-src.tgz > ${PRODUCT_NAME}-src.tgz.sha512 - -# Build binary tar -cd ${PRODUCT_NAME} -export TAG=${RELEASE_VERSION} -make dist diff --git a/tools/releasing/release.sh b/tools/releasing/release.sh new file mode 100755 index 0000000000..8338e60486 --- /dev/null +++ b/tools/releasing/release.sh @@ -0,0 +1,648 @@ +#!/usr/bin/env 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. +# + +# Apache SkyWalking Java Agent Release Script +# +# Usage: +# ./release.sh preflight Check tools and environment +# ./release.sh prepare Prepare release (branch, maven release:prepare, tag) +# ./release.sh stage Stage release (maven release:perform, build tars) +# ./release.sh upload Upload to Apache SVN dist/dev +# ./release.sh prepare-vote Run prepare + stage + upload, then generate vote email +# ./release.sh email [vote|announce] Generate email content +# ./release.sh promote Move from dist/dev to dist/release in SVN +# ./release.sh docker Build and push Docker images +# ./release.sh vote-passed Run promote + docker, then generate announce email +# ./release.sh cleanup Remove old release from dist/release + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +PRODUCT_NAME="apache-skywalking-java-agent" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +info() { echo -e "${GREEN}[INFO]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; } + +# ============================================================ +# preflight — check tools and environment +# ============================================================ +cmd_preflight() { + info "Running pre-flight checks..." + + local failed=0 + + # Required tools + for tool in git gpg svn shasum mvn java tar gh; do + if command -v "$tool" &>/dev/null; then + info " $tool: $(command -v $tool)" + else + error " $tool: NOT FOUND" + failed=1 + fi + done + + # Java version + local java_version + java_version=$(java -version 2>&1 | head -1) + info " Java: $java_version" + + # GPG key + local gpg_keys + gpg_keys=$(gpg --list-secret-keys --keyid-format SHORT 2>/dev/null | grep -c "sec" || true) + if [ "$gpg_keys" -eq 0 ]; then + error " GPG: No secret keys found. Import your GPG key first." + failed=1 + else + info " GPG: $gpg_keys secret key(s) found" + fi + + # GPG signing without password prompt + info " Testing GPG signing (should not ask for password)..." + local test_file + test_file=$(mktemp) + echo "test" > "$test_file" + if gpg --batch --yes --armor --detach-sig "$test_file" 2>/dev/null; then + info " GPG signing: OK (no password prompt)" + rm -f "$test_file" "${test_file}.asc" + else + rm -f "$test_file" "${test_file}.asc" + echo "" + echo " GPG signing FAILED. The agent must be configured to cache the passphrase." + echo "" + echo " Options to fix:" + echo " 1. Configure gpg-agent with a longer cache TTL in ~/.gnupg/gpg-agent.conf:" + echo " default-cache-ttl 86400" + echo " max-cache-ttl 86400" + echo " Then: gpgconf --kill gpg-agent" + echo "" + echo " 2. Or run 'gpg --sign /dev/null' manually first to cache the passphrase." + echo "" + failed=1 + fi + + # Maven settings (Apache credentials) + local settings_file="${HOME}/.m2/settings.xml" + if [ -f "$settings_file" ]; then + if grep -q "apache.releases.https" "$settings_file"; then + info " Maven settings: apache.releases.https server found" + else + warn " Maven settings: apache.releases.https server NOT found in $settings_file" + failed=1 + fi + else + warn " Maven settings: $settings_file not found" + failed=1 + fi + + # Git status + cd "$PROJECT_ROOT" + if [ -n "$(git status --porcelain)" ]; then + warn " Git: working tree is dirty" + else + info " Git: working tree is clean" + fi + + local branch + branch=$(git rev-parse --abbrev-ref HEAD) + info " Git branch: $branch" + + if [ "$failed" -ne 0 ]; then + echo "" + error "Pre-flight checks failed. Fix the issues above before releasing." + fi + + echo "" + info "All pre-flight checks passed." +} + +# ============================================================ +# prepare — prepare the release (CHANGES.md, maven) +# ============================================================ +cmd_prepare() { + local version="${1:-}" + local next_version="${2:-}" + if [ -z "$version" ]; then + error "Usage: $0 prepare [next_version] (e.g., 9.7.0 9.8.0)" + fi + + cd "$PROJECT_ROOT" + + if [ -z "$next_version" ]; then + next_version=$(echo "$version" | awk -F. '{printf "%s.%s.%s", $1, $2+1, 0}') + fi + local branch_name="release/${version}" + + info "Preparing release ${version}..." + echo " Release version: ${version}" + echo " Tag: v${version}" + echo " Next dev version: ${next_version}-SNAPSHOT" + echo " Branch: ${branch_name}" + echo "" + read -rp "Continue? [y/N] " confirm + if [[ ! "$confirm" =~ ^[Yy]$ ]]; then + info "Aborted." + exit 0 + fi + + # Step 1: Create release branch from main + info "Creating branch ${branch_name}..." + git checkout -b "${branch_name}" + + # Step 2: Maven release:prepare + # This creates two commits: + # 1. [maven-release-plugin] prepare release vx.y.z (pom versions set to x.y.z) + # 2. [maven-release-plugin] prepare for next development iteration (pom versions set to next-SNAPSHOT) + # And a tag vx.y.z pointing to commit 1. + # CHANGES.md is kept as-is so the tag includes the full changelog. + info "Running maven release:prepare..." + ./mvnw release:clean + ./mvnw release:prepare -DautoVersionSubmodules=true -Pall \ + -DreleaseVersion="${version}" \ + -DdevelopmentVersion="${next_version}-SNAPSHOT" \ + -Dtag="v${version}" \ + -DpushChanges=false + + # Step 3: After the tag is created, move CHANGES.md for next dev cycle + info "Moving changelog to changes/changes-${version}.md..." + local changes_file="changes/changes-${version}.md" + + # Extract current version section from CHANGES.md + sed -n "/^${version}$/,/^------------------$/p" CHANGES.md | head -n -1 > "$changes_file" + grep "All issues and pull requests" CHANGES.md >> "$changes_file" || true + info "Created $changes_file" + + # Reset CHANGES.md for next development version + cat > CHANGES.md << EOF +Changes by Version +================== +Release Notes. + +${next_version} +------------------ + + +All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/xxx?closed=1) + +------------------ +Find change logs of all versions [here](changes). +EOF + + git add CHANGES.md "$changes_file" + git commit -m "Move ${version} changelog and reset for ${next_version} development" + + # Step 4: Push branch and tag + info "Pushing branch and tag..." + git push -u origin "${branch_name}" + git push origin "v${version}" + + # Step 5: Create PR + info "Creating pull request..." + if command -v gh &>/dev/null; then + gh pr create --base main --head "${branch_name}" \ + --title "Release ${version}" \ + --body "Release Apache SkyWalking Java Agent ${version}. + +- Maven release:prepare completed (tag \`v${version}\` created) +- CHANGES.md archived to \`changes/changes-${version}.md\` +- Next development version: ${next_version}-SNAPSHOT" + info "PR created." + else + warn "GitHub CLI (gh) not found. Create PR manually for branch ${branch_name}." + fi + + info "Release ${version} prepared." + info " Tag v${version} is ready." + info " PR created for branch ${branch_name} → main." + info "Next step: $0 stage" +} + +# ============================================================ +# stage — stage the release (maven, build source & binary tars) +# ============================================================ +cmd_stage() { + cd "$PROJECT_ROOT" + + # Detect version from latest tag + local version + version=$(git describe --tags --abbrev=0 | sed 's/^v//') + local tag_name="v${version}" + + info "Staging release ${version}..." + + # Maven release:perform + info "Running maven release:perform..." + ./mvnw release:perform -DskipTests -Pall + + # Build source and binary packages (inlined from create_release.sh) + info "Building source and binary packages..." + + cd "${SCRIPT_DIR}" + local product_dir="${PRODUCT_NAME}-${version}" + + rm -rf "${product_dir}" + mkdir "${product_dir}" + + git clone https://github.com/apache/skywalking-java.git "./${product_dir}" + cd "${product_dir}" + + TAG_EXIST=$(git tag -l "${tag_name}" | wc -l) + if [ "${TAG_EXIST}" -ne 1 ]; then + error "Could not find the tag named ${tag_name}" + fi + + git checkout "${tag_name}" + git submodule init + git submodule update + + # Generate static version properties (no Git info in source tar) + ./mvnw -q -pl apm-sniffer/apm-agent-core initialize \ + -DgenerateGitPropertiesFilename="$(pwd)/apm-sniffer/apm-agent-core/src/main/resources/skywalking-agent-version.properties" + + cd "${SCRIPT_DIR}" + + # Source tar + info "Creating source tar..." + tar czf "${product_dir}-src.tgz" \ + --exclude .git \ + --exclude .DS_Store \ + --exclude .github \ + --exclude .gitignore \ + --exclude .gitmodules \ + "${product_dir}" + + gpg --armor --detach-sig "${product_dir}-src.tgz" + shasum -a 512 "${product_dir}-src.tgz" > "${product_dir}-src.tgz.sha512" + + # Binary tar + info "Creating binary tar..." + cd "${product_dir}" + export TAG="${version}" + make dist + + echo "" + info "Release ${version} staged." + info "Source tar: ${SCRIPT_DIR}/${product_dir}-src.tgz" + info "Binary tar: ${SCRIPT_DIR}/${product_dir}/${PRODUCT_NAME}-${version}.tgz" + info "Next step: $0 upload" +} + +# ============================================================ +# upload — upload to Apache SVN dist/dev +# ============================================================ +cmd_upload() { + cd "$PROJECT_ROOT" + + local version + version=$(git describe --tags --abbrev=0 | sed 's/^v//') + local svn_dev="https://dist.apache.org/repos/dist/dev/skywalking/java-agent" + + info "Uploading release ${version} to Apache SVN (dist/dev)..." + + local staging_dir="${SCRIPT_DIR}/${PRODUCT_NAME}-${version}" + + # Verify files exist + local src_tar="${SCRIPT_DIR}/${PRODUCT_NAME}-${version}-src.tgz" + local bin_tar="${staging_dir}/${PRODUCT_NAME}-${version}.tgz" + + for f in "$src_tar" "${src_tar}.asc" "${src_tar}.sha512" \ + "$bin_tar" "${bin_tar}.asc" "${bin_tar}.sha512"; do + if [ ! -f "$f" ]; then + error "Missing file: $f. Run '$0 stage' first." + fi + done + + # Create SVN directory and upload + read -rp "SVN username (Apache ID): " svn_user + + local tmp_svn + tmp_svn=$(mktemp -d) + info "Checking out SVN dist/dev..." + svn checkout --depth empty "$svn_dev" "$tmp_svn" --username "$svn_user" + + mkdir -p "${tmp_svn}/${version}" + + cp "$src_tar" "${src_tar}.asc" "${src_tar}.sha512" "${tmp_svn}/${version}/" + cp "$bin_tar" "${bin_tar}.asc" "${bin_tar}.sha512" "${tmp_svn}/${version}/" + + cd "$tmp_svn" + svn add "${version}" + svn commit -m "Stage Apache SkyWalking Java Agent ${version}" --username "$svn_user" + + rm -rf "$tmp_svn" + info "Uploaded to ${svn_dev}/${version}" + info "Next step: $0 email vote" +} + +# ============================================================ +# email — generate email templates +# ============================================================ +cmd_email() { + local type="${1:-}" + if [[ ! "$type" =~ ^(vote|announce)$ ]]; then + error "Usage: $0 email [vote|announce]" + fi + + cd "$PROJECT_ROOT" + + local version + version=$(git describe --tags --abbrev=0 | sed 's/^v//') + local tag="v${version}" + local commit_id + commit_id=$(git rev-list -n1 "$tag" 2>/dev/null || echo "") + local submodule_commit + submodule_commit=$(git ls-tree "$tag" apm-protocol/apm-network/src/main/proto 2>/dev/null | awk '{print $3}' || echo "") + + # Get sha512 checksums + local src_sha512="" + local bin_sha512="" + local src_sha_file="${SCRIPT_DIR}/${PRODUCT_NAME}-${version}-src.tgz.sha512" + local bin_sha_file="${SCRIPT_DIR}/${PRODUCT_NAME}-${version}/${PRODUCT_NAME}-${version}.tgz.sha512" + [ -f "$src_sha_file" ] && src_sha512=$(cat "$src_sha_file") + [ -f "$bin_sha_file" ] && bin_sha512=$(cat "$bin_sha_file") + + echo "" + echo "============================================================" + + case "$type" in + vote) + cat << EOF +Mail to: dev@skywalking.apache.org +Subject: [VOTE] Release Apache SkyWalking Java Agent version ${version} + +Hi All, +This is a call for vote to release Apache SkyWalking Java Agent version ${version}. + +Release notes: + + * https://github.com/apache/skywalking-java/blob/master/changes/changes-${version}.md + +Release Candidate: + + * https://dist.apache.org/repos/dist/dev/skywalking/java-agent/${version} + * sha512 checksums + - ${src_sha512} + - ${bin_sha512} + +Maven 2 staging repository: + + * https://repository.apache.org/content/repositories//org/apache/skywalking/ + +Release Tag : + + * (Git Tag) v${version} + +Release CommitID : + + * https://github.com/apache/skywalking-java/tree/${commit_id} + * Git submodule + * apm-protocol/apm-network/src/main/proto: https://github.com/apache/skywalking-data-collect-protocol/tree/${submodule_commit} + +Keys to verify the Release Candidate : + + * https://dist.apache.org/repos/dist/release/skywalking/KEYS + +Guide to build the release from source : + + > ./mvnw clean package + +Voting will start now ($(date '+%B %d, %Y')) and will remain open for at least 72 hours, Request all PMC members to give their vote. +[ ] +1 Release this package. +[ ] +0 No opinion. +[ ] -1 Do not release this package because.... +EOF + ;; + announce) + cat << EOF +Mail to: dev@skywalking.apache.org, announce@apache.org +Subject: [ANNOUNCE] Apache SkyWalking Java Agent ${version} released + +Hi all, + +Apache SkyWalking Team is glad to announce the release of Apache SkyWalking Java Agent ${version}. + +SkyWalking: APM (application performance monitor) tool for distributed systems, +especially designed for microservices, cloud native and container-based (Docker, Kubernetes, Mesos) architectures. + +The Java Agent for Apache SkyWalking, which provides the native tracing/metrics/logging abilities for Java projects. + +This release contains a number of new features, bug fixes and improvements compared to +the previous version. The notable changes include: + +(Highlight key changes from changes-${version}.md) +1. ... +2. ... +3. ... + +Please refer to the change log for the complete list of changes: +https://github.com/apache/skywalking-java/blob/master/changes/changes-${version}.md + +Apache SkyWalking website: +http://skywalking.apache.org/ + +Downloads: +http://skywalking.apache.org/downloads/ + +Twitter: +https://twitter.com/AsfSkyWalking + +SkyWalking Resources: +- GitHub: https://github.com/apache/skywalking-java +- Issue: https://github.com/apache/skywalking/issues +- Mailing list: dev@skywalking.apache.org + + +- Apache SkyWalking Team +EOF + ;; + esac + + echo "============================================================" + echo "" + warn "Replace with the actual Nexus staging repository ID." +} + +# ============================================================ +# docker — build and push Docker images +# ============================================================ +cmd_docker() { + cd "$PROJECT_ROOT" + + local version + version=$(git describe --tags --abbrev=0 | sed 's/^v//') + + info "Building and pushing Docker images for ${version}..." + + local dist_tar="${SCRIPT_DIR}/${PRODUCT_NAME}-${version}/${PRODUCT_NAME}-${version}.tgz" + + if [ ! -f "$dist_tar" ]; then + error "Binary tar not found: $dist_tar. Run '$0 stage' first." + fi + + # Extract agent package + tar -xzf "$dist_tar" -C "$PROJECT_ROOT" + + export NAME=skywalking-java-agent + export HUB=apache + export TAG="$version" + + make docker.push.alpine docker.push.java8 docker.push.java11 docker.push.java17 docker.push.java21 docker.push.java25 + + info "Docker images pushed for ${version}." +} + +# ============================================================ +# promote — move from dist/dev to dist/release +# ============================================================ +cmd_promote() { + cd "$PROJECT_ROOT" + + local version + version=$(git describe --tags --abbrev=0 | sed 's/^v//') + + info "Promoting release ${version} from dist/dev to dist/release..." + + read -rp "SVN username (Apache ID): " svn_user + + svn mv "https://dist.apache.org/repos/dist/dev/skywalking/java-agent/${version}" \ + "https://dist.apache.org/repos/dist/release/skywalking/java-agent/${version}" \ + -m "Release Apache SkyWalking Java Agent ${version}" \ + --username "$svn_user" + + info "Release ${version} promoted." + info "Next steps:" + info " 1. Release the Nexus staging repository" + info " 2. Update website download page" + info " 3. Run: $0 email announce" + info " 4. Run: $0 docker" +} + +# ============================================================ +# cleanup — remove old release from dist/release +# ============================================================ +cmd_cleanup() { + local old_version="${1:-}" + if [ -z "$old_version" ]; then + error "Usage: $0 cleanup (e.g., 9.5.0)" + fi + + info "Removing old release ${old_version} from dist/release..." + + read -rp "SVN username (Apache ID): " svn_user + + svn rm "https://dist.apache.org/repos/dist/release/skywalking/java-agent/${old_version}" \ + -m "Remove old Apache SkyWalking Java Agent ${old_version} release" \ + --username "$svn_user" + + info "Removed ${old_version} from dist/release." + warn "Remember to update download page links to point to archive.apache.org." +} + +# ============================================================ +# prepare-vote — run all steps before the vote +# ============================================================ +cmd_prepare_vote() { + local version="${1:-}" + local next_version="${2:-}" + if [ -z "$version" ]; then + error "Usage: $0 prepare-vote [next_version] (e.g., 9.7.0 9.8.0)" + fi + + cmd_preflight + echo "" + cmd_prepare "$version" "$next_version" + echo "" + cmd_stage + echo "" + cmd_upload + echo "" + cmd_email vote +} + +# ============================================================ +# vote-passed — run all steps after the vote passes +# ============================================================ +cmd_vote_passed() { + local old_version="${1:-}" + + cmd_promote + echo "" + cmd_docker + echo "" + cmd_email announce + + if [ -n "$old_version" ]; then + echo "" + cmd_cleanup "$old_version" + else + echo "" + warn "To clean up an old release, run: $0 cleanup " + fi +} + +# ============================================================ +# Main dispatcher +# ============================================================ +main() { + local cmd="${1:-}" + shift || true + + case "$cmd" in + preflight) cmd_preflight "$@" ;; + prepare) cmd_prepare "$@" ;; + stage) cmd_stage "$@" ;; + upload) cmd_upload "$@" ;; + email) cmd_email "$@" ;; + docker) cmd_docker "$@" ;; + promote) cmd_promote "$@" ;; + cleanup) cmd_cleanup "$@" ;; + prepare-vote) cmd_prepare_vote "$@" ;; + vote-passed) cmd_vote_passed "$@" ;; + *) + echo "Apache SkyWalking Java Agent Release Tool" + echo "" + echo "Usage: $0 [args]" + echo "" + echo "Quick start (two-step release):" + echo " $0 prepare-vote 9.7.0 [9.8.0] # before vote (next version auto-calculated if omitted)" + echo " (wait for 72h vote to pass)" + echo " $0 vote-passed [old_version] # after vote" + echo "" + echo "Individual commands:" + echo " preflight Check tools and environment" + echo " prepare [next_ver] Prepare release (branch, tag, PR)" + echo " stage Stage release (maven release:perform, build tars)" + echo " upload Upload to Apache SVN dist/dev" + echo " prepare-vote [next_ver] Run preflight + prepare + stage + upload + vote email" + echo " email [vote|announce] Generate email content" + echo " promote Move from dist/dev to dist/release in SVN" + echo " docker Build and push Docker images" + echo " vote-passed [old_ver] Run promote + docker + announce email [+ cleanup]" + echo " cleanup Remove old release from dist/release" + ;; + esac +} + +main "$@" From 489ec3cb9c5272d28e60ab690687a69657c016ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Thu, 16 Apr 2026 13:53:53 +0800 Subject: [PATCH 106/114] Remove unnecessary maven.compiler overrides and add CI check (#806) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove `maven.compiler.release=17` from `spring-ai-1.x-plugin` — its source code uses no JDK 17+ language features; the `provided`-scope dependency on Spring AI doesn't require raising the compiler level. - Remove redundant `maven.compiler.source/target=8` from 6 other plugins (aerospike, jedis, nats, micronaut-http-server, micronaut-http-client, tomcat-10x) since JDK 8 is already the default. - Add `tools/plugin/check-compiler-overrides.sh` CI check with an allowlist to prevent unnecessary compiler overrides in future PRs. Currently allowed: `jdk-httpclient-plugin` (uses JDK 11 HttpClient API) and `jdk-http-plugin` (resets to blank). --- .claude/skills/new-plugin/SKILL.md | 6 ++ .github/workflows/ci.yaml | 2 + CLAUDE.md | 2 +- .../apm-sdk-plugin/aerospike-plugin/pom.xml | 4 - .../apm-sdk-plugin/jedis-plugins/pom.xml | 2 - .../micronaut-http-client-plugin/pom.xml | 5 -- .../micronaut-http-server-plugin/pom.xml | 5 -- .../nats-2.14.x-2.16.5-plugin/pom.xml | 5 -- .../spring-ai-1.x-plugin/pom.xml | 17 +++- .../spring/ai/v1/messages/InputMessages.java | 6 +- .../apm-sdk-plugin/tomcat-10x-plugin/pom.xml | 2 - tools/plugin/check-compiler-overrides.sh | 80 +++++++++++++++++++ 12 files changed, 110 insertions(+), 26 deletions(-) create mode 100755 tools/plugin/check-compiler-overrides.sh diff --git a/.claude/skills/new-plugin/SKILL.md b/.claude/skills/new-plugin/SKILL.md index d960d07058..14008fdf35 100644 --- a/.claude/skills/new-plugin/SKILL.md +++ b/.claude/skills/new-plugin/SKILL.md @@ -249,6 +249,11 @@ apm-sniffer/optional-plugins/{name}-plugin/ - Never bundle target library classes into the plugin JAR - If the plugin needs a 3rd-party utility not already in agent-core, discuss with maintainers first +**CRITICAL compiler level rule:** +- Do NOT set `maven.compiler.release` or `maven.compiler.source/target` unless the plugin source code itself uses JDK 9+ language features (e.g., `var`, records, sealed classes, `java.net.http.HttpClient`). +- A `provided`-scope dependency targeting a higher JDK (e.g., Spring AI requires JDK 17+) does NOT require raising the compiler level — the plugin only references the library's API at compile time. +- Bootstrap plugins like `jdk-httpclient-plugin` (which uses JDK 11 `HttpClient` API directly in plugin source code) legitimately need a higher compiler target. SDK plugins and optional plugins generally should not. + ### Register in Parent POM Add the new module to the parent `pom.xml`: @@ -1052,6 +1057,7 @@ Before submitting: - [ ] Types in `PascalCase`, variables in `camelCase` - [ ] Imports only from `java.*`, `org.apache.skywalking.*`, `net.bytebuddy.*` (in instrumentation files) - [ ] Target library dependencies in `provided` scope +- [ ] No unnecessary `maven.compiler.release` or `maven.compiler.source/target` (only set if plugin source uses JDK 9+ language features) - [ ] Using V2 API for new plugins - [ ] String literals (not `.class` references) in instrumentation definitions - [ ] `skywalking-plugin.def` registered diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0bc7a9c0e9..e8a4a2bfb1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -73,6 +73,8 @@ jobs: java-version: ${{ matrix.java-version }} - name: Check Javaagent Plugin List run: tools/plugin/check-javaagent-plugin-list.sh + - name: Check Plugin Compiler Overrides + run: tools/plugin/check-compiler-overrides.sh - name: Install and Test run: ./mvnw -q --batch-mode clean verify install javadoc:javadoc diff --git a/CLAUDE.md b/CLAUDE.md index 02c69c17e3..ab26fb02eb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -292,5 +292,5 @@ GitHub Actions workflows: 3. **Respect checkstyle**: No System.out, no @author, no Chinese characters 4. **Use Lombok**: Prefer annotations over boilerplate code 5. **Test both unit and E2E**: Different test patterns for different scopes -6. **Java version compatibility**: Agent core must maintain Java 8 compatibility, but individual plugins may target higher JDK versions (e.g., jdk-httpclient-plugin for JDK 11+, virtual-thread plugins for JDK 21+) +6. **Java version compatibility**: Agent core must maintain Java 8 compatibility, but individual plugins may target higher JDK versions (e.g., jdk-httpclient-plugin for JDK 11+, virtual-thread plugins for JDK 21+). **Do NOT set `maven.compiler.release` or `maven.compiler.source/target` in a plugin pom.xml unless the plugin source code itself uses JDK 9+ language features.** A `provided`-scope dependency targeting a higher JDK does not require raising the compiler level — the plugin code only references the library's API at compile time and does not need to match the library's runtime JDK requirement. 7. **For plugin development**: See `apm-sniffer/apm-sdk-plugin/CLAUDE.md` and `apm-sniffer/bootstrap-plugins/CLAUDE.md` diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml index f2c5ac64f4..be9a30a3a3 100644 --- a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml @@ -38,9 +38,5 @@ provided - - 8 - 8 - diff --git a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml index a337f0c2f8..440d8a3232 100644 --- a/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jedis-plugins/pom.xml @@ -24,8 +24,6 @@ - 8 - 8 UTF-8 diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml index a0955c19d2..0dbafa710d 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-client-plugin/pom.xml @@ -27,11 +27,6 @@ micronaut-http-client-plugin - - 8 - 8 - - io.projectreactor diff --git a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml index a8fd47deac..df12088c75 100644 --- a/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/micronaut-plugins/micronaut-http-server-plugin/pom.xml @@ -28,11 +28,6 @@ micronaut-http-server-plugin jar - - 8 - 8 - - io.micronaut diff --git a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml index 60bba313b0..6e115d8ade 100644 --- a/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/nats-2.14.x-2.16.5-plugin/pom.xml @@ -29,11 +29,6 @@ nats-2.14.x-2.16.5-plugin jar - - 8 - 8 - - io.nats diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml index b6ea5c9863..295cf9d8ed 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml @@ -32,7 +32,10 @@ http://maven.apache.org - 17 + + @@ -44,4 +47,16 @@ + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + false + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/InputMessages.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/InputMessages.java index 794748bc49..9a1b10ae8c 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/InputMessages.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/messages/InputMessages.java @@ -93,7 +93,10 @@ public TextPart(String content) { @Override public Map toMap() { - return Map.of("type", "text", "content", content != null ? content : ""); + Map map = new LinkedHashMap<>(); + map.put("type", "text"); + map.put("content", content != null ? content : ""); + return map; } } @@ -268,4 +271,5 @@ private static List toolMessageParts(Message message) { return parts; } + } diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml index 62896f4b61..7c54849e28 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml @@ -28,8 +28,6 @@ tomcat-10x-plugin - 8 - 8 10.0.22 diff --git a/tools/plugin/check-compiler-overrides.sh b/tools/plugin/check-compiler-overrides.sh new file mode 100755 index 0000000000..601bcfe4d8 --- /dev/null +++ b/tools/plugin/check-compiler-overrides.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env 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. +# + +# Check that plugin pom.xml files do not set maven.compiler.release, +# maven.compiler.source, or maven.compiler.target unless they are on +# the allowlist. A provided-scope dependency targeting a higher JDK +# does NOT justify raising the compiler level — only plugin source code +# that uses JDK 9+ language features does. + +WORK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd ../.. && pwd)" + +# Plugins that override maven.compiler.release. Two categories: +# +# 1. JDK 11/17+ required: plugin source code uses higher-JDK APIs directly +# (e.g., java.net.http.HttpClient). Sets maven.compiler.release=11/17/etc. +# +# 2. API visibility only: plugin source code is JDK 8 compatible, but provided +# dependencies use java.lang.Record or other JDK 9+ types. Sets +# (blank) to cancel the parent's --release 8 +# restriction, so the compiler can resolve those types. Bytecode remains +# JDK 8 compatible. +ALLOWLIST=( + # Category 1: JDK 11+ required + "bootstrap-plugins/jdk-httpclient-plugin" + # Category 2: API visibility only + "bootstrap-plugins/jdk-http-plugin" + "spring-plugins/spring-ai-1.x-plugin" +) + +EXIT_CODE=0 + +while IFS= read -r pom; do + # Check if this pom is on the allowlist + allowed=false + for entry in "${ALLOWLIST[@]}"; do + if [[ "${pom}" == *"${entry}"* ]]; then + allowed=true + break + fi + done + + if [ "${allowed}" = true ]; then + continue + fi + + # Report the violation + echo "ERROR: ${pom} sets a compiler level override but is not on the allowlist." + echo " If the plugin source code uses JDK 9+ language features, add it to the" + echo " allowlist in tools/plugin/check-compiler-overrides.sh." + echo " Otherwise, remove the compiler override from the pom.xml." + echo "" + EXIT_CODE=1 +done < <(grep -rl "maven\.compiler\.\(release\|source\|target\)" \ + "${WORK_DIR}/apm-sniffer/apm-sdk-plugin" \ + "${WORK_DIR}/apm-sniffer/bootstrap-plugins" \ + "${WORK_DIR}/apm-sniffer/optional-plugins" \ + "${WORK_DIR}/apm-sniffer/optional-reporter-plugins" \ + --include="pom.xml") + +if [ ${EXIT_CODE} -eq 0 ]; then + echo "Compiler override check passed." +fi + +exit ${EXIT_CODE} From e0e8b3c8c304735991e057d431910ed1f4a57cdd Mon Sep 17 00:00:00 2001 From: Guimu <30684111+daguimu@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:49:35 +0800 Subject: [PATCH 107/114] Apply SQL_BODY_MAX_LENGTH to ClickHouse JDBC plugin span tags (#807) --- CHANGES.md | 1 + .../ClickHouseStatementTracingWrapper.java | 3 +- ...ClickHouseStatementTracingWrapperTest.java | 117 +++++++++++++++++ .../ClickHousePrepareStatementTracing.java | 3 +- ...ClickHousePrepareStatementTracingTest.java | 118 ++++++++++++++++++ 5 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapperTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHousePrepareStatementTracingTest.java diff --git a/CHANGES.md b/CHANGES.md index ef6a81a3e4..3a9514fdc6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -24,6 +24,7 @@ Release Notes. * Add Elasticsearch Java client (co.elastic.clients:elasticsearch-java) plugin for 7.16.x-9.x. * Only publish `apm-application-toolkit` modules to Maven Central. Agent and plugins are distributed via download package and Docker images. * Add unified release script (`tools/releasing/release.sh`) with two-step flow: `prepare-vote` and `vote-passed`. +* Fix an issue where `JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH` was not honored by clickhouse-0.3.1 and clickhouse-0.3.2.x plugins. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapper.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapper.java index 6f2e9bcaa0..2599fb3455 100644 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapper.java +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapper.java @@ -23,6 +23,7 @@ import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.plugin.jdbc.SqlBodyUtil; import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; /** @@ -37,7 +38,7 @@ public static T of(ConnectionInfo connectionInfo, String methodName, String try { Tags.DB_TYPE.set(span, connectionInfo.getDBType()); Tags.DB_INSTANCE.set(span, connectionInfo.getDatabaseName()); - Tags.DB_STATEMENT.set(span, sql); + Tags.DB_STATEMENT.set(span, SqlBodyUtil.limitSqlBodySize(sql)); span.setComponent(connectionInfo.getComponent()); SpanLayer.asDB(span); return supplier.get(); diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapperTest.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapperTest.java new file mode 100644 index 0000000000..3c330478fc --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.1-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHouseStatementTracingWrapperTest.java @@ -0,0 +1,117 @@ +/* + * 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.jdbc.clickhouse; + +import java.util.List; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.context.util.TagValuePair; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.helper.SpanHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.JDBCPluginConfig; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * Verify that {@link ClickHouseStatementTracingWrapper} truncates the SQL body + * recorded on the exit span according to {@link JDBCPluginConfig.Plugin.JDBC#SQL_BODY_MAX_LENGTH}. + */ +@RunWith(TracingSegmentRunner.class) +public class ClickHouseStatementTracingWrapperTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + private ConnectionInfo connectionInfo; + + private int originalLimit; + + @Before + public void setUp() { + connectionInfo = new ConnectionInfo( + ComponentsDefine.CLICKHOUSE_JDBC_DRIVER, "ClickHouse", "127.0.0.1", 8123, "default"); + originalLimit = JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH; + } + + @After + public void tearDown() { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = originalLimit; + } + + @Test + public void shortSqlIsRecordedAsIs() throws Exception { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 2048; + String sql = "SELECT 1"; + + ClickHouseStatementTracingWrapper.of(connectionInfo, "execute", sql, () -> Boolean.TRUE); + + assertThat(dbStatementTagValue(), is(sql)); + } + + @Test + public void longSqlIsTruncatedToConfiguredLimit() throws Exception { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 16; + // Longer than the limit, so the helper must truncate to first 16 chars and append "..." + String sql = "SELECT * FROM table_with_many_cols"; + + ClickHouseStatementTracingWrapper.of(connectionInfo, "execute", sql, () -> Boolean.TRUE); + + assertThat(dbStatementTagValue(), is(sql.substring(0, 16) + "...")); + } + + @Test + public void negativeLimitDisablesTruncation() throws Exception { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = -1; + StringBuilder builder = new StringBuilder("SELECT "); + for (int i = 0; i < 1000; i++) { + builder.append("a, "); + } + builder.append("a FROM t"); + String sql = builder.toString(); + + ClickHouseStatementTracingWrapper.of(connectionInfo, "execute", sql, () -> Boolean.TRUE); + + assertThat(dbStatementTagValue(), is(sql)); + } + + private String dbStatementTagValue() { + List traceSegments = segmentStorage.getTraceSegments(); + assertThat(traceSegments.size(), is(1)); + List spans = SegmentHelper.getSpans(traceSegments.get(0)); + assertThat(spans.size(), is(1)); + List tags = SpanHelper.getTags(spans.get(0)); + // tag order: db.type, db.instance, db.statement + return (String) tags.get(2).getValue(); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v32/ClickHousePrepareStatementTracing.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v32/ClickHousePrepareStatementTracing.java index 292dd413a7..5c94003cf2 100644 --- a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v32/ClickHousePrepareStatementTracing.java +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/v32/ClickHousePrepareStatementTracing.java @@ -22,6 +22,7 @@ import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.plugin.jdbc.SqlBodyUtil; import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; import java.sql.SQLException; @@ -39,7 +40,7 @@ public static T of(ConnectionInfo connectionInfo, String methodName, String try { Tags.DB_TYPE.set(span, connectionInfo.getDBType()); Tags.DB_INSTANCE.set(span, connectionInfo.getDatabaseName()); - Tags.DB_STATEMENT.set(span, sql); + Tags.DB_STATEMENT.set(span, SqlBodyUtil.limitSqlBodySize(sql)); span.setComponent(connectionInfo.getComponent()); SpanLayer.asDB(span); return supplier.get(); diff --git a/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHousePrepareStatementTracingTest.java b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHousePrepareStatementTracingTest.java new file mode 100644 index 0000000000..49d2de6ff2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/clickhouse-0.3.2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jdbc/clickhouse/ClickHousePrepareStatementTracingTest.java @@ -0,0 +1,118 @@ +/* + * 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.jdbc.clickhouse; + +import java.util.List; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.context.util.TagValuePair; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.helper.SpanHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.jdbc.JDBCPluginConfig; +import org.apache.skywalking.apm.plugin.jdbc.clickhouse.v32.ClickHousePrepareStatementTracing; +import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * Verify that {@link ClickHousePrepareStatementTracing} truncates the SQL body + * recorded on the exit span according to {@link JDBCPluginConfig.Plugin.JDBC#SQL_BODY_MAX_LENGTH}. + */ +@RunWith(TracingSegmentRunner.class) +public class ClickHousePrepareStatementTracingTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + private ConnectionInfo connectionInfo; + + private int originalLimit; + + @Before + public void setUp() { + connectionInfo = new ConnectionInfo( + ComponentsDefine.CLICKHOUSE_JDBC_DRIVER, "ClickHouse", "127.0.0.1", 8123, "test"); + originalLimit = JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH; + } + + @After + public void tearDown() { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = originalLimit; + } + + @Test + public void shortSqlIsRecordedAsIs() throws Exception { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 2048; + String sql = "SELECT 1"; + + ClickHousePrepareStatementTracing.of(connectionInfo, "execute", sql, () -> Boolean.TRUE); + + assertThat(dbStatementTagValue(), is(sql)); + } + + @Test + public void longSqlIsTruncatedToConfiguredLimit() throws Exception { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = 16; + // Longer than the configured limit, so the helper must truncate to the first 16 chars and append "..." + String sql = "SELECT * FROM table_with_many_cols"; + + ClickHousePrepareStatementTracing.of(connectionInfo, "execute", sql, () -> Boolean.TRUE); + + assertThat(dbStatementTagValue(), is(sql.substring(0, 16) + "...")); + } + + @Test + public void negativeLimitDisablesTruncation() throws Exception { + JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH = -1; + StringBuilder builder = new StringBuilder("SELECT "); + for (int i = 0; i < 1000; i++) { + builder.append("a, "); + } + builder.append("a FROM t"); + String sql = builder.toString(); + + ClickHousePrepareStatementTracing.of(connectionInfo, "execute", sql, () -> Boolean.TRUE); + + assertThat(dbStatementTagValue(), is(sql)); + } + + private String dbStatementTagValue() { + List traceSegments = segmentStorage.getTraceSegments(); + assertThat(traceSegments.size(), is(1)); + List spans = SegmentHelper.getSpans(traceSegments.get(0)); + assertThat(spans.size(), is(1)); + List tags = SpanHelper.getTags(spans.get(0)); + // tag order: db.type, db.instance, db.statement + return (String) tags.get(2).getValue(); + } +} From 9e770bfd1f7386d97af1b78cebbf72038a8d4936 Mon Sep 17 00:00:00 2001 From: peachisai <2581009893@qq.com> Date: Wed, 3 Jun 2026 11:57:16 +0800 Subject: [PATCH 108/114] Support tracing RAG retrieval in Spring AI 1.x plugin (#808) --- CHANGES.md | 1 + .../apm/agent/core/context/tag/Tags.java | 15 ++ .../spring-ai-1.x-plugin/pom.xml | 7 + ...tionVectorStoreConstructorInterceptor.java | 48 +++++ ...ractObservationVectorStoreInterceptor.java | 171 ++++++++++++++++++ .../ai/v1/ChatModelCallInterceptor.java | 5 +- .../ai/v1/ChatModelStreamInterceptor.java | 12 +- .../ai/v1/EmbeddingModelInterceptor.java | 70 +++++++ .../ai/v1/VectorStoreEnhanceContext.java | 37 ++++ .../common/EmbeddingModelEnhanceContext.java | 36 ++++ .../ai/v1/common/ErrorTypeResolver.java | 80 ++++++++ .../ai/v1/config/SpringAiPluginConfig.java | 17 ++ .../spring/ai/v1/contant/Constants.java | 2 + ...ObservationVectorStoreInstrumentation.java | 92 ++++++++++ .../define/EmbeddingModelInstrumentation.java | 75 ++++++++ .../src/main/resources/skywalking-plugin.def | 2 + apm-sniffer/config/agent.config | 10 +- .../spring-ai-1.x-scenario/bin/startup.sh | 2 +- .../config/expectedData.yaml | 43 +++++ .../scenarios/spring-ai-1.x-scenario/pom.xml | 5 + .../httpclient/config/ChatClientConfig.java | 27 +++ .../httpclient/controller/CaseController.java | 23 +++ .../controller/LLMMockController.java | 137 ++++++++++++++ .../src/main/resources/application.yaml | 3 + 24 files changed, 915 insertions(+), 5 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/EmbeddingModelInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/VectorStoreEnhanceContext.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/EmbeddingModelEnhanceContext.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/ErrorTypeResolver.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/AbstractObservationVectorStoreInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/EmbeddingModelInstrumentation.java diff --git a/CHANGES.md b/CHANGES.md index 3a9514fdc6..0bf6869120 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -25,6 +25,7 @@ Release Notes. * Only publish `apm-application-toolkit` modules to Maven Central. Agent and plugins are distributed via download package and Docker images. * Add unified release script (`tools/releasing/release.sh`) with two-step flow: `prepare-vote` and `vote-passed`. * Fix an issue where `JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH` was not honored by clickhouse-0.3.1 and clickhouse-0.3.2.x plugins. +- Add tracing support for vector-store retrieval operations. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java index 3d0b9f37cb..8acb2b9879 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java @@ -250,6 +250,21 @@ public static final class HTTP { */ public static final StringTag GEN_AI_OUTPUT_MESSAGES = new StringTag(42, "gen_ai.output.messages"); + /** + * GEN_AI_DATA_SOURCE_ID represents the data source identifier. + */ + public static final StringTag GEN_AI_DATA_SOURCE_ID = new StringTag(43, "gen_ai.data_source.id"); + + /** + * GEN_AI_RETRIEVAL_DOCUMENTS represents the documents retrieved. + */ + public static final StringTag GEN_AI_RETRIEVAL_DOCUMENTS = new StringTag(44, "gen_ai.retrieval.documents"); + + /** + * GEN_AI_RETRIEVAL_QUERY_TEXT represents the query text used for retrieval. + */ + public static final StringTag GEN_AI_RETRIEVAL_QUERY_TEXT = new StringTag(45, "gen_ai.retrieval.query.text"); + /** * Creates a {@code StringTag} with the given key and cache it, if it's created before, simply return it without * creating a new one. diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml index 295cf9d8ed..583ce9c90c 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/pom.xml @@ -46,6 +46,13 @@ provided + + org.springframework.ai + spring-ai-vector-store + 1.1.0 + provided + + diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreConstructorInterceptor.java new file mode 100644 index 0000000000..faefa999bc --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreConstructorInterceptor.java @@ -0,0 +1,48 @@ +/* + * 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.spring.ai.v1; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.EmbeddingModelEnhanceContext; + +public class AbstractObservationVectorStoreConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + objInst.setSkyWalkingDynamicField(new VectorStoreEnhanceContext(resolveContextFromArgument(allArguments[0]))); + } + + private EmbeddingModelEnhanceContext resolveContextFromArgument(Object argument) { + if (argument instanceof EnhancedInstance) { + return getOrCreateContext((EnhancedInstance) argument); + } + return null; + } + + private EmbeddingModelEnhanceContext getOrCreateContext(EnhancedInstance embeddingModel) { + Object context = embeddingModel.getSkyWalkingDynamicField(); + if (context instanceof EmbeddingModelEnhanceContext) { + return (EmbeddingModelEnhanceContext) context; + } + EmbeddingModelEnhanceContext embeddingModelEnhanceContext = new EmbeddingModelEnhanceContext(); + embeddingModel.setSkyWalkingDynamicField(embeddingModelEnhanceContext); + return embeddingModelEnhanceContext; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreInterceptor.java new file mode 100644 index 0000000000..4b278b6c87 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreInterceptor.java @@ -0,0 +1,171 @@ +/* + * 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.spring.ai.v1; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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.agent.core.util.GsonUtil; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ErrorTypeResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.config.SpringAiPluginConfig; +import org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants; +import org.springframework.ai.document.Document; +import org.springframework.ai.vectorstore.SearchRequest; +import org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore; +import org.springframework.ai.vectorstore.observation.VectorStoreObservationContext; +import org.springframework.util.StringUtils; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class AbstractObservationVectorStoreInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + SearchRequest request = (SearchRequest) allArguments[0]; + String dataSourceId = objInst.getClass().getSimpleName(); + + try { + VectorStoreObservationContext context = + createObservationContext(objInst, request); + + String resolved = + resolveDataSourceId(context, objInst); + + if (StringUtils.hasText(resolved)) { + dataSourceId = resolved; + } + } catch (Throwable ignored) { + + } + + AbstractSpan span = ContextManager.createExitSpan(Constants.RETRIEVAL + "/" + dataSourceId, dataSourceId); + + SpanLayer.asGenAI(span); + span.setComponent(ComponentsDefine.SPRING_AI); + Tags.GEN_AI_OPERATION_NAME.set(span, Constants.RETRIEVAL); + Tags.GEN_AI_DATA_SOURCE_ID.set(span, dataSourceId); + String model = resolveEmbeddingModelName(objInst); + if (StringUtils.hasText(model)) { + Tags.GEN_AI_REQUEST_MODEL.set(span, model); + } + + if (request != null) { + Tags.GEN_AI_TOP_K.set(span, String.valueOf(request.getTopK())); + String query = request.getQuery(); + if (StringUtils.hasText(query) && SpringAiPluginConfig.Plugin.SpringAi.COLLECT_RETRIEVAL_QUERY) { + int limit = SpringAiPluginConfig.Plugin.SpringAi.RETRIEVAL_QUERY_LENGTH_LIMIT; + if (limit > 0 && query.length() > limit) { + query = query.substring(0, limit); + } + Tags.GEN_AI_RETRIEVAL_QUERY_TEXT.set(span, query); + } + } + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + if (!ContextManager.isActive()) { + return ret; + } + try { + if (ret instanceof List && SpringAiPluginConfig.Plugin.SpringAi.COLLECT_RETRIEVAL_DOCUMENTS) { + Tags.GEN_AI_RETRIEVAL_DOCUMENTS.set(ContextManager.activeSpan(), toDocumentsJson((List) ret)); + } + } finally { + ContextManager.stopSpan(); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + if (ContextManager.isActive()) { + AbstractSpan span = ContextManager.activeSpan(); + span.log(t); + ErrorTypeResolver.setErrorType(span, t); + } + } + + private VectorStoreObservationContext createObservationContext(EnhancedInstance objInst, SearchRequest request) { + VectorStoreObservationContext.Builder builder = ((AbstractObservationVectorStore) objInst) + .createObservationContextBuilder(VectorStoreObservationContext.Operation.QUERY.value()); + if (request != null) { + builder.queryRequest(request); + } + return builder.build(); + } + + private String resolveEmbeddingModelName(EnhancedInstance objInst) { + Object context = objInst.getSkyWalkingDynamicField(); + if (context instanceof VectorStoreEnhanceContext) { + return ((VectorStoreEnhanceContext) context).getEmbeddingModelName(); + } + return null; + } + + private String resolveDataSourceId(VectorStoreObservationContext context, EnhancedInstance objInst) { + StringBuilder dataSourceId = new StringBuilder(); + appendDataSourcePart(dataSourceId, context.getDatabaseSystem()); + appendDataSourcePart(dataSourceId, context.getNamespace()); + appendDataSourcePart(dataSourceId, context.getCollectionName()); + if (dataSourceId.length() > 0) { + return dataSourceId.toString(); + } + return objInst.getClass().getSimpleName(); + } + + private void appendDataSourcePart(StringBuilder dataSourceId, String value) { + if (!StringUtils.hasText(value)) { + return; + } + if (dataSourceId.length() > 0) { + dataSourceId.append('/'); + } + dataSourceId.append(value); + } + + private String toDocumentsJson(List documents) { + List> retrievalDocuments = new ArrayList<>(documents.size()); + for (Object item : documents) { + if (!(item instanceof Document)) { + continue; + } + Document document = (Document) item; + Map documentMap = new LinkedHashMap<>(); + documentMap.put("id", document.getId()); + if (document.getScore() != null) { + documentMap.put("score", document.getScore()); + } + retrievalDocuments.add(documentMap); + } + return GsonUtil.toJson(retrievalDocuments); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java index 302db3c407..73f62629c1 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java @@ -26,6 +26,7 @@ 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.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ErrorTypeResolver; import org.apache.skywalking.apm.plugin.spring.ai.v1.config.SpringAiPluginConfig; import org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants; import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.InputMessages; @@ -129,7 +130,9 @@ 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); + AbstractSpan span = ContextManager.activeSpan(); + span.log(t); + ErrorTypeResolver.setErrorType(span, t); } } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java index 1674e82011..7d1b380573 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java @@ -27,6 +27,7 @@ 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.plugin.spring.ai.v1.common.ChatModelMetadataResolver; +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.ErrorTypeResolver; import org.apache.skywalking.apm.plugin.spring.ai.v1.config.SpringAiPluginConfig; import org.apache.skywalking.apm.plugin.spring.ai.v1.contant.Constants; import org.apache.skywalking.apm.plugin.spring.ai.v1.messages.InputMessages; @@ -94,11 +95,16 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA return flux .doOnNext(response -> onStreamNext(span, response, state)) - .doOnError(span::log) + .doOnError(t -> recordError(span, t)) .doFinally(signalType -> onStreamFinally(span, allArguments, state)) .contextWrite(c -> c.put(Constants.SKYWALKING_CONTEXT_SNAPSHOT, snapshot)); } + private void recordError(AbstractSpan span, Throwable t) { + span.log(t); + ErrorTypeResolver.setErrorType(span, t); + } + private void onStreamNext(AbstractSpan span, ChatResponse response, StreamState state) { state.lastResponseRef.set(response); @@ -248,7 +254,9 @@ private Long readAndClearStartTime() { @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { if (ContextManager.isActive()) { - ContextManager.activeSpan().log(t); + AbstractSpan span = ContextManager.activeSpan(); + span.log(t); + ErrorTypeResolver.setErrorType(span, t); } } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/EmbeddingModelInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/EmbeddingModelInterceptor.java new file mode 100644 index 0000000000..8e2b57fae9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/EmbeddingModelInterceptor.java @@ -0,0 +1,70 @@ +/* + * 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.spring.ai.v1; + +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.plugin.spring.ai.v1.common.EmbeddingModelEnhanceContext; +import org.springframework.ai.embedding.EmbeddingResponse; +import org.springframework.ai.embedding.EmbeddingResponseMetadata; +import org.springframework.util.StringUtils; + +import java.lang.reflect.Method; + +public class EmbeddingModelInterceptor 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 EmbeddingResponse)) { + return ret; + } + + EmbeddingResponseMetadata metadata = ((EmbeddingResponse) ret).getMetadata(); + if (metadata == null) { + return ret; + } + String model = metadata.getModel(); + if (!StringUtils.hasText(model)) { + return ret; + } + EmbeddingModelEnhanceContext context = getOrCreateContext(objInst); + context.setEmbeddingModelNameIfAbsent(model); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { + } + + private EmbeddingModelEnhanceContext getOrCreateContext(EnhancedInstance objInst) { + Object context = objInst.getSkyWalkingDynamicField(); + if (context instanceof EmbeddingModelEnhanceContext) { + return (EmbeddingModelEnhanceContext) context; + } + EmbeddingModelEnhanceContext embeddingModelEnhanceContext = new EmbeddingModelEnhanceContext(); + objInst.setSkyWalkingDynamicField(embeddingModelEnhanceContext); + return embeddingModelEnhanceContext; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/VectorStoreEnhanceContext.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/VectorStoreEnhanceContext.java new file mode 100644 index 0000000000..76916a59ea --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/VectorStoreEnhanceContext.java @@ -0,0 +1,37 @@ +/* + * 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.spring.ai.v1; + +import org.apache.skywalking.apm.plugin.spring.ai.v1.common.EmbeddingModelEnhanceContext; + +public class VectorStoreEnhanceContext { + + private final EmbeddingModelEnhanceContext embeddingModelEnhanceContext; + + public VectorStoreEnhanceContext(EmbeddingModelEnhanceContext embeddingModelEnhanceContext) { + this.embeddingModelEnhanceContext = embeddingModelEnhanceContext; + } + + public String getEmbeddingModelName() { + if (embeddingModelEnhanceContext == null) { + return null; + } + return embeddingModelEnhanceContext.getEmbeddingModelName(); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/EmbeddingModelEnhanceContext.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/EmbeddingModelEnhanceContext.java new file mode 100644 index 0000000000..199bd97cd4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/EmbeddingModelEnhanceContext.java @@ -0,0 +1,36 @@ +/* + * 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.spring.ai.v1.common; + +import org.springframework.util.StringUtils; + +public class EmbeddingModelEnhanceContext { + + private volatile String embeddingModelName; + + public String getEmbeddingModelName() { + return embeddingModelName; + } + + public void setEmbeddingModelNameIfAbsent(String embeddingModelName) { + if (!StringUtils.hasText(this.embeddingModelName) && StringUtils.hasText(embeddingModelName)) { + this.embeddingModelName = embeddingModelName; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/ErrorTypeResolver.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/ErrorTypeResolver.java new file mode 100644 index 0000000000..1d3172cf3d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/common/ErrorTypeResolver.java @@ -0,0 +1,80 @@ +/* + * 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.spring.ai.v1.common; + +import org.apache.skywalking.apm.agent.core.context.tag.AbstractTag; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; + +import javax.net.ssl.SSLHandshakeException; +import java.net.SocketTimeoutException; +import java.security.cert.CertPathValidatorException; +import java.security.cert.CertificateException; +import java.util.concurrent.TimeoutException; + +public final class ErrorTypeResolver { + + private static final AbstractTag ERROR_TYPE = Tags.ofKey("error.type"); + private static final String TIMEOUT = "timeout"; + private static final String SERVER_CERTIFICATE_INVALID = "server_certificate_invalid"; + + private ErrorTypeResolver() { + } + + public static void setErrorType(AbstractSpan span, Throwable throwable) { + span.tag(ERROR_TYPE, resolve(throwable)); + } + + private static String resolve(Throwable throwable) { + if (matches(throwable, ErrorTypeResolver::isTimeout)) { + return TIMEOUT; + } + if (matches(throwable, ErrorTypeResolver::isCertificateInvalid)) { + return SERVER_CERTIFICATE_INVALID; + } + return throwable.getClass().getName(); + } + + private static boolean isTimeout(Throwable throwable) { + return throwable instanceof SocketTimeoutException + || throwable instanceof TimeoutException + || throwable.getClass().getName().contains("TimeoutException"); + } + + private static boolean isCertificateInvalid(Throwable throwable) { + return throwable instanceof SSLHandshakeException + || throwable instanceof CertificateException + || throwable instanceof CertPathValidatorException; + } + + private static boolean matches(Throwable throwable, Matcher matcher) { + Throwable current = throwable; + while (current != null) { + if (matcher.matches(current)) { + return true; + } + current = current.getCause(); + } + return false; + } + + private interface Matcher { + boolean matches(Throwable throwable); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java index d2d5eef6f6..6a348c622b 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java @@ -69,6 +69,23 @@ public static class SpringAi { * Whether to collect the execution result (output) of the tool/function call. */ public static boolean COLLECT_TOOL_OUTPUT = false; + + /** + * Whether to collect the query of the rag call. + */ + public static boolean COLLECT_RETRIEVAL_QUERY = false; + + /** + * The maximum characters of the collected rag query content. + * If the content exceeds this limit, it will be truncated. + * Use a negative value to represent no limit, but be aware this could cause OOM. + */ + public static int RETRIEVAL_QUERY_LENGTH_LIMIT = 1024; + + /** + * Whether to collect the documents of the rag call. + */ + public static boolean COLLECT_RETRIEVAL_DOCUMENTS = false; } } } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/contant/Constants.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/contant/Constants.java index 7348a0c11f..688f4c321a 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/contant/Constants.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/contant/Constants.java @@ -27,5 +27,7 @@ public class Constants { public static final String EXECUTE_TOOL = "execute_tool"; + public static final String RETRIEVAL = "retrieval"; + public static final String DEFAULT_COMPLETIONS_PATH = "/v1/chat/completions"; } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/AbstractObservationVectorStoreInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/AbstractObservationVectorStoreInstrumentation.java new file mode 100644 index 0000000000..f379c0464c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/AbstractObservationVectorStoreInstrumentation.java @@ -0,0 +1,92 @@ +/* + * 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.spring.ai.v1.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 org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch; +import org.apache.skywalking.apm.agent.core.plugin.match.logical.LogicalMatchOperation; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; + +public class AbstractObservationVectorStoreInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.vectorstore.observation.AbstractObservationVectorStore"; + + private static final String INTERCEPT_METHOD = "doSimilaritySearch"; + + private static final String INTERCEPTOR_CLASS = + "org.apache.skywalking.apm.plugin.spring.ai.v1.AbstractObservationVectorStoreInterceptor"; + + private static final String CONSTRUCTOR_INTERCEPTOR_CLASS = + "org.apache.skywalking.apm.plugin.spring.ai.v1.AbstractObservationVectorStoreConstructorInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return LogicalMatchOperation.or(HierarchyMatch.byHierarchyMatch(ENHANCE_CLASS), MultiClassNameMatch.byMultiClassMatch(ENHANCE_CLASS)); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgumentWithType(0, "org.springframework.ai.embedding.EmbeddingModel"); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(INTERCEPT_METHOD) + .and(takesArguments(1)) + .and(takesArgumentWithType(0, "org.springframework.ai.vectorstore.SearchRequest")); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/EmbeddingModelInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/EmbeddingModelInstrumentation.java new file mode 100644 index 0000000000..12a327ae29 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/define/EmbeddingModelInstrumentation.java @@ -0,0 +1,75 @@ +/* + * 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.spring.ai.v1.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 net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; + +public class EmbeddingModelInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.springframework.ai.embedding.EmbeddingModel"; + + private static final String INTERCEPT_METHOD = "call"; + + private static final String INTERCEPTOR_CLASS = + "org.apache.skywalking.apm.plugin.spring.ai.v1.EmbeddingModelInterceptor"; + + @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 getMethodsMatcher() { + return named(INTERCEPT_METHOD) + .and(takesArguments(1)) + .and(takesArgumentWithType(0, "org.springframework.ai.embedding.EmbeddingRequest")); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/resources/skywalking-plugin.def index 5c7eec110c..62e1f6af3e 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/resources/skywalking-plugin.def @@ -15,8 +15,10 @@ # limitations under the License. spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.ChatModelInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.EmbeddingModelInstrumentation spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.ToolCallbackInstrumentation spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.DefaultToolCallingManagerInstrumentation +spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.AbstractObservationVectorStoreInstrumentation spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.AnthropicApiInstrumentation spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.DeepSeekApiInstrumentation spring-ai-1.x=org.apache.skywalking.apm.plugin.spring.ai.v1.define.provider.HuggingfaceChatModelInstrumentation diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index 38c9bbf8d5..146d0d94fc 100755 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -362,4 +362,12 @@ plugin.springai.content_collect_threshold_tokens=${SW_PLUGIN_SPRINGAI_CONTENT_CO # Whether to collect the arguments (input parameters) of the tool/function call. plugin.springai.collect_tool_input=${SW_PLUGIN_SPRINGAI_COLLECT_TOOL_INPUT:false} # Whether to collect the execution result (output) of the tool/function call. -plugin.springai.collect_tool_output=${SW_PLUGIN_SPRINGAI_COLLECT_TOOL_OUTPUT:false} \ No newline at end of file +plugin.springai.collect_tool_output=${SW_PLUGIN_SPRINGAI_COLLECT_TOOL_OUTPUT:false} +# Whether to collect the query of the rag call. +plugin.springai.collect_retrieval_query=${SW_PLUGIN_SPRINGAI_COLLECT_RETRIEVAL_QUERY:false} +# The maximum characters of the collected rag query. +# If the content exceeds this limit, it will be truncated. +# Use a negative value to represent no limit, but be aware this could cause OOM. +plugin.springai.retrieval_query=${SW_PLUGIN_SPRINGAI_RETRIEVAL_QUERY_LENGTH_LIMIT:1024} +# Whether to collect the documents of the rag call. +plugin.springai.collect_retrieval_documents=${SW_PLUGIN_SPRINGAI_COLLECT_RETRIEVAL_DOCUMENTS:false} \ No newline at end of file diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/bin/startup.sh b/test/plugin/scenarios/spring-ai-1.x-scenario/bin/startup.sh index 8cb423ece2..9950f6fed6 100644 --- a/test/plugin/scenarios/spring-ai-1.x-scenario/bin/startup.sh +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/bin/startup.sh @@ -18,4 +18,4 @@ home="$(cd "$(dirname $0)"; pwd)" -java -Dskywalking.plugin.springai.collect_input_messages=true -Dskywalking.plugin.springai.collect_output_messages=true -Dskywalking.plugin.springai.collect_tool_input=true -Dskywalking.plugin.springai.collect_tool_output=true -jar ${agent_opts} ${home}/../libs/spring-ai-1.x-scenario.jar & \ No newline at end of file +java -Dskywalking.plugin.springai.collect_input_messages=true -Dskywalking.plugin.springai.collect_output_messages=true -Dskywalking.plugin.springai.collect_tool_input=true -Dskywalking.plugin.springai.collect_tool_output=true -Dskywalking.plugin.springai.collect_retrieval_query=true -Dskywalking.plugin.springai.collect_retrieval_documents=true -jar ${agent_opts} ${home}/../libs/spring-ai-1.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml index 5f40e79a48..d714ae2542 100644 --- a/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/config/expectedData.yaml @@ -142,6 +142,49 @@ segmentItems: - { key: http.method, value: POST } - { key: http.status_code, value: '200' } + - operationName: retrieval/simple/in-memory-map + parentSpanId: 0 + spanId: 6 + spanLayer: GenAI + startTime: not null + endTime: not null + componentId: 178 + spanType: Exit + peer: simple/in-memory-map + tags: + - { key: gen_ai.operation.name, value: retrieval } + - { key: gen_ai.data_source.id, value: simple/in-memory-map } + - { key: gen_ai.request.model, value: text-embedding-3-small } + - { key: gen_ai.request.top_k, value: '2' } + - { key: gen_ai.retrieval.query.text, value: 'What is Apache SkyWalking?' } + - { key: gen_ai.retrieval.documents, value: not null } + + - operationName: Spring-ai/openai/call + parentSpanId: 0 + spanId: 7 + spanLayer: GenAI + startTime: not null + endTime: not null + componentId: 173 + isError: false + spanType: Exit + peer: http://localhost:8080/spring-ai-1.x-scenario/llm/v1/chat/completions + skipAnalysis: false + tags: + - { key: gen_ai.operation.name, value: chat } + - { key: gen_ai.provider.name, value: openai } + - { key: gen_ai.request.model, value: gpt-4.1-2025-04-14 } + - { key: gen_ai.request.temperature, value: '0.7' } + - { key: gen_ai.request.top_p, value: '0.9' } + - { key: gen_ai.response.id, value: chatcmpl-DknJunZ3tgcSkKiv } + - { key: gen_ai.response.model, value: gpt-4.1-2025-04-14 } + - { key: gen_ai.usage.input_tokens, value: '72' } + - { key: gen_ai.usage.output_tokens, value: '25' } + - { key: gen_ai.client.token.usage, value: '97' } + - { key: gen_ai.response.finish_reasons, value: STOP } + - { key: gen_ai.input.messages, value: not null } + - { key: gen_ai.output.messages, value: not null } + - operationName: GET:/spring-ai-1.x-scenario/case/spring-ai-1.x-scenario-case parentSpanId: -1 spanId: 0 diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/pom.xml b/test/plugin/scenarios/spring-ai-1.x-scenario/pom.xml index b9d39f538a..0d508db8b0 100644 --- a/test/plugin/scenarios/spring-ai-1.x-scenario/pom.xml +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/pom.xml @@ -55,6 +55,11 @@ spring-ai-starter-model-openai + + org.springframework.ai + spring-ai-vector-store + + org.projectlombok lombok diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/config/ChatClientConfig.java b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/config/ChatClientConfig.java index 79fde137ab..02d0f3466b 100644 --- a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/config/ChatClientConfig.java +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/config/ChatClientConfig.java @@ -17,10 +17,18 @@ package test.apache.skywalking.apm.testcase.jdk.httpclient.config; +import org.springframework.ai.document.Document; +import org.springframework.ai.embedding.EmbeddingModel; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.openai.OpenAiChatModel; +import org.springframework.ai.vectorstore.SimpleVectorStore; +import org.springframework.ai.vectorstore.VectorStore; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; + +import java.util.ArrayList; +import java.util.List; @Configuration public class ChatClientConfig { @@ -29,4 +37,23 @@ public class ChatClientConfig { public ChatClient openAIChatClient(OpenAiChatModel model) { return ChatClient.create(model); } + + @Bean + @Lazy + public VectorStore vectorStore(EmbeddingModel embeddingModel) { + SimpleVectorStore vectorStore = SimpleVectorStore.builder(embeddingModel).build(); + + List documentList = new ArrayList<>(); + documentList.add(new Document("The 2025 AI Summit is scheduled for October 10-12 in San Francisco. " + + "The event will focus on Generative AI and Autonomous Agents.")); + documentList.add(new Document("Apache SkyWalking is an open-source Application Performance Management system " + + "designed for microservices, cloud native, and container-based architectures.")); + documentList.add(new Document("Spring AI provides a unified interface for interacting with different " + + "AI Models, allowing developers to switch between providers with minimal code changes.")); + documentList.add(new Document("A new distributed tracing protocol, TraceContext v2, was proposed " + + "on August 25, 2025, to improve cross-cloud observability.")); + + vectorStore.add(documentList); + return vectorStore; + } } diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java index d6512b726e..73dc1b15bc 100644 --- a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/CaseController.java @@ -18,12 +18,18 @@ package test.apache.skywalking.apm.testcase.jdk.httpclient.controller; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.document.Document; +import org.springframework.ai.vectorstore.SearchRequest; +import org.springframework.ai.vectorstore.VectorStore; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import test.apache.skywalking.apm.testcase.jdk.httpclient.tool.WeatherTool; +import java.util.stream.Collectors; + @RestController @RequestMapping("/case") @RequiredArgsConstructor @@ -31,6 +37,7 @@ public class CaseController { private final WeatherTool weatherTool; private final ChatClient chatClient; + private final ObjectProvider vectorStoreProvider; @GetMapping("/healthCheck") public String healthCheck() { @@ -63,6 +70,22 @@ public String testCase() throws Exception { .doOnNext(System.out::println) .blockLast(); + String question = "What is Apache SkyWalking?"; + VectorStore vectorStore = vectorStoreProvider.getObject(); + String context = vectorStore.similaritySearch(SearchRequest.builder() + .query(question) + .topK(2) + .build()) + .stream() + .map(Document::getText) + .collect(Collectors.joining("\n")); + + chatClient + .prompt(question) + .system("Answer using only the following context:\n" + context) + .call() + .content(); + return "success"; } } diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/LLMMockController.java b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/LLMMockController.java index 5221245280..d63482c5fd 100644 --- a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/LLMMockController.java +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/jdk/httpclient/controller/LLMMockController.java @@ -21,6 +21,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -177,6 +178,60 @@ public Object completions(@RequestBody JSONObject request, HttpServletResponse r } """; + String ragLlmResponse = """ + { + "choices": [ + { + "finish_reason": "stop", + "index": 0, + "logprobs": null, + "message": { + "annotations": [], + "content": "Apache SkyWalking is an open-source Application Performance Management system designed for microservices, cloud native, and container-based architectures.", + "refusal": null, + "role": "assistant" + } + } + ], + "created": 1780045046, + "id": "chatcmpl-DknJunZ3tgcSkKiv", + "model": "gpt-4.1-2025-04-14", + "object": "chat.completion", + "service_tier": "default", + "system_fingerprint": "fp_a7294185dc", + "usage": { + "completion_tokens": 25, + "completion_tokens_details": { + "accepted_prediction_tokens": 0, + "audio_tokens": 0, + "reasoning_tokens": 0, + "rejected_prediction_tokens": 0 + }, + "latency_checkpoint": { + "engine_tbt_ms": 23, + "engine_ttft_ms": 672, + "engine_ttlt_ms": 1259, + "pre_inference_ms": 157, + "service_tbt_ms": 610, + "service_ttft_ms": 12302, + "service_ttlt_ms": 27518, + "total_duration_ms": 27381, + "user_visible_ttft_ms": 12145 + }, + "prompt_tokens": 72, + "prompt_tokens_details": { + "audio_tokens": 0, + "cached_tokens": 0 + }, + "total_tokens": 97 + } + } + """; + + if (isRagLlmRequest(messages)) { + return JSON.parseObject(ragLlmResponse); + } + if ("tool".equals(lastRole)) { return JSON.parseObject(finalResponse); } @@ -227,4 +282,86 @@ private String escapeJson(String input) { if (input == null) return ""; return input.replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r"); } + + private boolean isRagLlmRequest(JSONArray messages) { + if (messages == null || messages.size() < 2) { + return false; + } + + JSONObject lastMessage = messages.getJSONObject(messages.size() - 1); + if (!"user".equals(lastMessage.getString("role")) + || !"What is Apache SkyWalking?".equals(lastMessage.getString("content"))) { + return false; + } + + for (int i = 0; i < messages.size() - 1; i++) { + JSONObject message = messages.getJSONObject(i); + if (!"system".equals(message.getString("role"))) { + continue; + } + String content = message.getString("content"); + if (content != null + && content.startsWith("Answer using only the following context:") + && content.contains("Apache SkyWalking is an open-source Application Performance Management system")) { + return true; + } + } + return false; + } + + @PostMapping("/v1/embeddings") + public Object embeddings(@RequestBody JSONObject request) { + Object input = request.get("input"); + JSONArray inputs = input instanceof JSONArray ? (JSONArray) input : new JSONArray(); + if (!(input instanceof JSONArray)) { + inputs.add(String.valueOf(input)); + } + + JSONArray data = new JSONArray(); + for (int i = 0; i < inputs.size(); i++) { + JSONObject item = new JSONObject(); + item.put("object", "embedding"); + item.put("index", i); + item.put("embedding", embeddingFor(inputs.getString(i))); + data.add(item); + } + + JSONObject usage = new JSONObject(); + usage.put("prompt_tokens", inputs.size()); + usage.put("total_tokens", inputs.size()); + + JSONObject response = new JSONObject(); + response.put("object", "list"); + response.put("model", "text-embedding-3-small"); + response.put("data", data); + response.put("usage", usage); + return response; + } + + private JSONArray embeddingFor(String input) { + String text = input == null ? "" : input.toLowerCase(); + double[] values = new double[]{ + score(text, "summit", "san francisco", "generative", "autonomous"), + score(text, "skywalking", "apm", "microservices", "cloud native"), + score(text, "spring ai", "models", "providers"), + score(text, "tracecontext", "tracing", "observability"), + 0.1 + }; + + JSONArray embedding = new JSONArray(); + for (double value : values) { + embedding.add(value); + } + return embedding; + } + + private double score(String text, String... keywords) { + double value = 0.0; + for (String keyword : keywords) { + if (text.contains(keyword)) { + value += 1.0; + } + } + return value; + } } diff --git a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/resources/application.yaml index c4f5c58851..fceabe447e 100644 --- a/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/resources/application.yaml +++ b/test/plugin/scenarios/spring-ai-1.x-scenario/src/main/resources/application.yaml @@ -30,6 +30,9 @@ spring: temperature: 0.7 max-tokens: 1000 top-p: 0.9 + embedding: + options: + model: text-embedding-3-small From 1acfda1082169c53bda876da7ac07025cbbee9c9 Mon Sep 17 00:00:00 2001 From: peachisai <2581009893@qq.com> Date: Wed, 3 Jun 2026 13:51:12 +0800 Subject: [PATCH 109/114] fix the config of plugin.springai.retrieval_query_length_limit (#809) --- .../ai/v1/AbstractObservationVectorStoreInterceptor.java | 2 +- .../apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java | 4 ++-- .../apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java | 4 ++-- .../apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java | 2 +- apm-sniffer/config/agent.config | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreInterceptor.java index 4b278b6c87..473ffb5b95 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/AbstractObservationVectorStoreInterceptor.java @@ -80,7 +80,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr String query = request.getQuery(); if (StringUtils.hasText(query) && SpringAiPluginConfig.Plugin.SpringAi.COLLECT_RETRIEVAL_QUERY) { int limit = SpringAiPluginConfig.Plugin.SpringAi.RETRIEVAL_QUERY_LENGTH_LIMIT; - if (limit > 0 && query.length() > limit) { + if (limit >= 0 && query.length() > limit) { query = query.substring(0, limit); } Tags.GEN_AI_RETRIEVAL_QUERY_TEXT.set(span, query); diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java index 73f62629c1..2e25f9e13b 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelCallInterceptor.java @@ -161,7 +161,7 @@ private void collectPrompt(AbstractSpan span, Object[] allArguments) { InputMessages inputMessages = InputMessages.fromPrompt(prompt); String inputMessagesJson = inputMessages.toJson(); int limit = SpringAiPluginConfig.Plugin.SpringAi.INPUT_MESSAGES_LENGTH_LIMIT; - if (limit > 0 && inputMessagesJson.length() > limit) { + if (limit >= 0 && inputMessagesJson.length() > limit) { inputMessagesJson = inputMessagesJson.substring(0, limit); } @@ -174,7 +174,7 @@ private void collectCompletion(AbstractSpan span, ChatResponse response) { String outputMessagesJson = outputMessages.toJson(); int limit = SpringAiPluginConfig.Plugin.SpringAi.OUTPUT_MESSAGES_LENGTH_LIMIT; - if (limit > 0 && outputMessagesJson.length() > limit) { + if (limit >= 0 && outputMessagesJson.length() > limit) { outputMessagesJson = outputMessagesJson.substring(0, limit); } Tags.GEN_AI_OUTPUT_MESSAGES.set(span, outputMessagesJson); diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java index 7d1b380573..7231a99aa1 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/ChatModelStreamInterceptor.java @@ -218,7 +218,7 @@ private void collectPrompt(AbstractSpan span, Object[] allArguments) { String inputMessagesJson = inputMessages.toJson(); int limit = SpringAiPluginConfig.Plugin.SpringAi.INPUT_MESSAGES_LENGTH_LIMIT; - if (limit > 0 && inputMessagesJson.length() > limit) { + if (limit >= 0 && inputMessagesJson.length() > limit) { inputMessagesJson = inputMessagesJson.substring(0, limit); } @@ -238,7 +238,7 @@ private void collectCompletion(AbstractSpan span, StreamState state) { String outputMessagesJson = outputMessages.toJson(); int limit = SpringAiPluginConfig.Plugin.SpringAi.OUTPUT_MESSAGES_LENGTH_LIMIT; - if (limit > 0 && outputMessagesJson.length() > limit) { + if (limit >= 0 && outputMessagesJson.length() > limit) { outputMessagesJson = outputMessagesJson.substring(0, limit); } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java index 6a348c622b..b0a56635ce 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-ai-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/ai/v1/config/SpringAiPluginConfig.java @@ -85,7 +85,7 @@ public static class SpringAi { /** * Whether to collect the documents of the rag call. */ - public static boolean COLLECT_RETRIEVAL_DOCUMENTS = false; + public static boolean COLLECT_RETRIEVAL_DOCUMENTS = false; } } } diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config index 146d0d94fc..b9101f1f1c 100755 --- a/apm-sniffer/config/agent.config +++ b/apm-sniffer/config/agent.config @@ -368,6 +368,6 @@ plugin.springai.collect_retrieval_query=${SW_PLUGIN_SPRINGAI_COLLECT_RETRIEVAL_Q # The maximum characters of the collected rag query. # If the content exceeds this limit, it will be truncated. # Use a negative value to represent no limit, but be aware this could cause OOM. -plugin.springai.retrieval_query=${SW_PLUGIN_SPRINGAI_RETRIEVAL_QUERY_LENGTH_LIMIT:1024} +plugin.springai.retrieval_query_length_limit=${SW_PLUGIN_SPRINGAI_RETRIEVAL_QUERY_LENGTH_LIMIT:1024} # Whether to collect the documents of the rag call. plugin.springai.collect_retrieval_documents=${SW_PLUGIN_SPRINGAI_COLLECT_RETRIEVAL_DOCUMENTS:false} \ No newline at end of file From a1d69cbbe95bda8e09c1533d5154fb0c901d38f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Wed, 1 Jul 2026 17:34:55 +0800 Subject: [PATCH 110/114] Fix agent lifecycle events: Start instance name and Shutdown delivery (#810) --- CHANGES.md | 1 + .../apm/agent/core/boot/ServiceManager.java | 6 +- .../core/remote/EventReportServiceClient.java | 32 +++--- .../core/boot/ServiceManagerOrderingTest.java | 107 ++++++++++++++++++ .../core/kafka/KafkaProducerManager.java | 10 +- .../core/kafka/KafkaProducerManagerTest.java | 6 + 6 files changed, 138 insertions(+), 24 deletions(-) create mode 100644 apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerOrderingTest.java diff --git a/CHANGES.md b/CHANGES.md index 0bf6869120..8136757432 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ Release Notes. * Add unified release script (`tools/releasing/release.sh`) with two-step flow: `prepare-vote` and `vote-passed`. * Fix an issue where `JDBCPluginConfig.Plugin.JDBC.SQL_BODY_MAX_LENGTH` was not honored by clickhouse-0.3.1 and clickhouse-0.3.2.x plugins. - Add tracing support for vector-store retrieval operations. +* Fix agent lifecycle events: the Start event now carries the service instance name, and the Shutdown event is delivered on graceful JVM exit. `ServiceManager` prepares/starts higher-priority `BootService`s first and shuts them down last (matching `BootService#priority()`), and the shutdown event refreshes its gRPC deadline before sending. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/249?closed=1) diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java index 015596ad26..222a1d8221 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java @@ -50,7 +50,7 @@ public void boot() { } public void shutdown() { - bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority).reversed()).forEach(service -> { + bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority)).forEach(service -> { try { service.shutdown(); } catch (Throwable e) { @@ -103,7 +103,7 @@ private Map loadAllServices() { } private void prepare() { - bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority)).forEach(service -> { + bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority).reversed()).forEach(service -> { try { service.prepare(); } catch (Throwable e) { @@ -113,7 +113,7 @@ private void prepare() { } private void startup() { - bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority)).forEach(service -> { + bootedServices.values().stream().sorted(Comparator.comparingInt(BootService::priority).reversed()).forEach(service -> { try { service.boot(); } catch (Throwable e) { diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/EventReportServiceClient.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/EventReportServiceClient.java index 73860707fd..475405c726 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/EventReportServiceClient.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/EventReportServiceClient.java @@ -50,11 +50,13 @@ public class EventReportServiceClient implements BootService, GRPCChannelListene private final AtomicBoolean reported = new AtomicBoolean(); + private volatile boolean bootCompleted; + private Event.Builder startingEvent; - private EventServiceGrpc.EventServiceStub eventServiceStub; + private volatile EventServiceGrpc.EventServiceStub eventServiceStub; - private GRPCChannelStatus status; + private volatile GRPCChannelStatus status = GRPCChannelStatus.DISCONNECT; @Override public void prepare() throws Throwable { @@ -91,6 +93,7 @@ public void boot() throws Throwable { @Override public void onComplete() throws Throwable { startingEvent.setEndTime(System.currentTimeMillis()); + bootCompleted = true; reportStartingEvent(); } @@ -117,7 +120,8 @@ public void shutdown() throws Throwable { ) .setLayer(EVENT_LAYER_NAME); - final StreamObserver collector = eventServiceStub.collect(new StreamObserver() { + final EventServiceGrpc.EventServiceStub stub = eventServiceStub.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS); + final StreamObserver collector = stub.collect(new StreamObserver() { @Override public void onNext(final Commands commands) { ServiceManager.INSTANCE.findService(CommandService.class).receiveCommand(commands); @@ -143,25 +147,27 @@ public void onCompleted() { @Override public void statusChanged(final GRPCChannelStatus status) { + if (CONNECTED.equals(status)) { + final Channel channel = ServiceManager.INSTANCE.findService(GRPCChannelManager.class).getChannel(); + eventServiceStub = EventServiceGrpc.newStub(channel); + } this.status = status; - if (!CONNECTED.equals(status)) { - return; + if (CONNECTED.equals(status)) { + reportStartingEvent(); } - - final Channel channel = ServiceManager.INSTANCE.findService(GRPCChannelManager.class).getChannel(); - eventServiceStub = EventServiceGrpc.newStub(channel); - eventServiceStub = eventServiceStub.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS); - - reportStartingEvent(); } private void reportStartingEvent() { - if (reported.compareAndSet(false, true)) { + if (!bootCompleted || !CONNECTED.equals(status)) { + return; + } + if (!reported.compareAndSet(false, true)) { return; } - final StreamObserver collector = eventServiceStub.collect(new StreamObserver() { + final EventServiceGrpc.EventServiceStub stub = eventServiceStub.withDeadlineAfter(GRPC_UPSTREAM_TIMEOUT, TimeUnit.SECONDS); + final StreamObserver collector = stub.collect(new StreamObserver() { @Override public void onNext(final Commands commands) { ServiceManager.INSTANCE.findService(CommandService.class).receiveCommand(commands); diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerOrderingTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerOrderingTest.java new file mode 100644 index 0000000000..b232c5540c --- /dev/null +++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/boot/ServiceManagerOrderingTest.java @@ -0,0 +1,107 @@ +/* + * 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.agent.core.boot; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.junit.After; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +public class ServiceManagerOrderingTest { + + private final List prepareOrder = new ArrayList<>(); + private final List bootOrder = new ArrayList<>(); + private final List shutdownOrder = new ArrayList<>(); + + private class RecordingService implements BootService { + private final String name; + private final int priority; + + private RecordingService(String name, int priority) { + this.name = name; + this.priority = priority; + } + + @Override + public void prepare() { + prepareOrder.add(name); + } + + @Override + public void boot() { + bootOrder.add(name); + } + + @Override + public void onComplete() { + } + + @Override + public void shutdown() { + shutdownOrder.add(name); + } + + @Override + public int priority() { + return priority; + } + } + + @After + public void tearDown() throws Exception { + setBootedServices(new LinkedHashMap<>()); + } + + @Test + public void higherPriorityBootsFirstAndShutsDownLast() throws Exception { + Map services = new LinkedHashMap<>(); + services.put(Integer.class, new RecordingService("low", 0)); + services.put(Long.class, new RecordingService("high", Integer.MAX_VALUE)); + services.put(Short.class, new RecordingService("mid", 100)); + setBootedServices(services); + + invoke("prepare"); + invoke("startup"); + ServiceManager.INSTANCE.shutdown(); + + assertThat(prepareOrder, is(Arrays.asList("high", "mid", "low"))); + assertThat(bootOrder, is(Arrays.asList("high", "mid", "low"))); + assertThat(shutdownOrder, is(Arrays.asList("low", "mid", "high"))); + } + + private void setBootedServices(Map services) throws Exception { + Field field = ServiceManager.class.getDeclaredField("bootedServices"); + field.setAccessible(true); + field.set(ServiceManager.INSTANCE, services); + } + + private void invoke(String method) throws Exception { + Method m = ServiceManager.class.getDeclaredMethod(method); + m.setAccessible(true); + m.invoke(ServiceManager.INSTANCE); + } +} diff --git a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/main/java/org/apache/skywalking/apm/agent/core/kafka/KafkaProducerManager.java b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/main/java/org/apache/skywalking/apm/agent/core/kafka/KafkaProducerManager.java index 31dc8482f1..d8dafc0438 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/main/java/org/apache/skywalking/apm/agent/core/kafka/KafkaProducerManager.java +++ b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/main/java/org/apache/skywalking/apm/agent/core/kafka/KafkaProducerManager.java @@ -44,12 +44,10 @@ import org.apache.skywalking.apm.agent.core.boot.BootService; import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor; import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory; -import org.apache.skywalking.apm.agent.core.boot.ServiceManager; import org.apache.skywalking.apm.agent.core.kafka.KafkaReporterPluginConfig.Plugin.Kafka; 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.agent.core.plugin.loader.AgentClassLoader; -import org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager; import org.apache.skywalking.apm.util.RunnableWithExceptionProtection; import org.apache.skywalking.apm.util.StringUtil; @@ -183,14 +181,10 @@ public final KafkaProducer getProducer() { return producer; } - /** - * make kafka producer init later but before {@link GRPCChannelManager} - * - * @return priority value - */ + // Higher than the Kafka reporters sharing this producer, so the producer closes only after they stop. @Override public int priority() { - return ServiceManager.INSTANCE.findService(GRPCChannelManager.class).priority() - 1; + return 1; } @Override diff --git a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/test/java/org/apache/skywalking/apm/agent/core/kafka/KafkaProducerManagerTest.java b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/test/java/org/apache/skywalking/apm/agent/core/kafka/KafkaProducerManagerTest.java index 3a6b7c2d49..ed3c593f5e 100644 --- a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/test/java/org/apache/skywalking/apm/agent/core/kafka/KafkaProducerManagerTest.java +++ b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/test/java/org/apache/skywalking/apm/agent/core/kafka/KafkaProducerManagerTest.java @@ -19,6 +19,7 @@ package org.apache.skywalking.apm.agent.core.kafka; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.lang.reflect.Method; import java.util.Properties; import java.util.concurrent.atomic.AtomicInteger; @@ -46,6 +47,11 @@ public void testAddListener() throws Exception { assertEquals(counter.get(), times); } + @Test + public void outranksKafkaReportersSoProducerClosesLast() { + assertTrue(new KafkaProducerManager().priority() > new KafkaTraceSegmentServiceClient().priority()); + } + @Test public void testFormatTopicNameThenRegister() { KafkaProducerManager kafkaProducerManager = new KafkaProducerManager(); From a9b0cf4ca1a424dcd8b1cdad7beb6289465ea363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Wed, 1 Jul 2026 20:05:22 +0800 Subject: [PATCH 111/114] Pin docker/login-action to an ASF-approved commit SHA (#811) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ASF org-wide GitHub Actions allow-list requires third-party actions to be pinned to a reviewed commit SHA rather than a floating version tag. publish-docker.yaml referenced docker/login-action@v1.10.0, which the allow-list rejects. Pin it to 650006c6eb7dba73a995cc03b0b2d7f5ca915bee (v4.2.0) — the same approved SHA used by the apache/skywalking repo and present in apache/infrastructure-actions' approved_patterns.yml. --- .github/workflows/publish-docker.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-docker.yaml b/.github/workflows/publish-docker.yaml index 1eb75de778..13dd95e4ae 100644 --- a/.github/workflows/publish-docker.yaml +++ b/.github/workflows/publish-docker.yaml @@ -91,7 +91,7 @@ jobs: docker info echo "DOCKER_API_VERSION=$(docker version --format '{{.Server.APIVersion}}')" >> "$GITHUB_ENV" - name: Log in to the Container registry - uses: docker/login-action@v1.10.0 + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: registry: ${{ env.HUB }} username: ${{ github.actor }} From f572a767c73fff053c2ae96fd515fa3776b52216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Tue, 7 Jul 2026 07:14:18 +0800 Subject: [PATCH 112/114] Fix include_http_headers on Spring Boot 3.x/Jakarta, unify Tomcat/Jetty servlet plugins (#13938) (#812) * Fix include_http_headers on Spring Boot 3.x/Jakarta, unify Tomcat/Jetty servlet plugins (#13938) Add a shared servlet-commons module: a JDK-typed, namespace-agnostic servlet request/response wrapper that resolves javax.servlet vs jakarta.servlet at runtime through a single dispatch point. Refactor the Spring MVC commons onto it, removing the fragile static javax/jakarta detection that silently dropped plugin.http.include_http_headers on Jakarta (Spring Boot 3.x) applications. Merge the duplicated servlet plugin pairs, each now covering both namespaces: - tomcat-7.x-8.x + tomcat-10x -> tomcat - jetty-server-9.x + jetty-server-11.x -> jetty-server Breaking change: the plugin definition names change accordingly; update any plugin.exclude_plugins (SW_EXCLUDE_PLUGINS) settings referencing the old names. Add E2E scenarios spring-boot-3.x (Boot 3 embedded Tomcat 10, jakarta) and spring-boot-2.x (Boot 2, javax mirror), both asserting http.headers and http.params; port the tomcat/jetty interceptor unit tests to the merged modules; bump jakarta framework versions (one per minor); update docs. * Add servlet-commons provided dependency to mvc-annotation-4.x-plugin Its interceptor unit tests exercise the commons AbstractMethodInterceptor, which now references servlet-commons' HttpRequestWrappers. Since commons declares servlet-commons at provided (non-transitive) scope, it was absent from the 4.x plugin's test classpath, causing NoClassDefFoundError in CI. --- .github/workflows/plugins-jdk17-test.1.yaml | 1 + .github/workflows/plugins-test.2.yaml | 1 + CHANGES.md | 2 + .../jetty/v11/server/ForwardInterceptor.java | 63 --- .../AbstractWitnessInstrumentation.java | 39 -- .../jetty-server-9.x-plugin/pom.xml | 45 --- .../jetty/v9/server/HandleInterceptor.java | 90 ----- .../define/DispatcherInstrumentation.java | 80 ---- .../server/define/JettyInstrumentation.java | 71 ---- .../pom.xml | 17 +- .../apm/plugin/jetty/server}/Constants.java | 2 +- .../jetty}/server/ForwardInterceptor.java | 9 +- .../jetty}/server/HandleInterceptor.java | 24 +- .../AbstractWitnessInstrumentation.java | 8 +- .../define/DispatcherInstrumentation.java | 4 +- .../server/define/JettyInstrumentation.java | 4 +- .../src/main/resources/skywalking-plugin.def | 4 +- .../jetty}/server/HandleInterceptorTest.java | 17 +- .../apm-sdk-plugin/jetty-plugin/pom.xml | 3 +- apm-sniffer/apm-sdk-plugin/pom.xml | 4 +- .../pom.xml | 55 +-- .../plugin/servlet/HttpRequestWrapper.java | 47 +++ .../plugin/servlet/HttpRequestWrappers.java | 158 ++++++++ .../plugin/servlet/HttpResponseWrapper.java | 29 ++ .../plugin/servlet/HttpResponseWrappers.java | 100 +++++ .../servlet/HttpRequestWrappersTest.java | 80 ++++ .../servlet/HttpResponseWrappersTest.java | 65 +++ .../mvc-annotation-4.x-plugin/pom.xml | 9 + .../mvc-annotation-commons/pom.xml | 20 +- .../commons/HttpServletRequestWrappers.java | 112 ------ .../spring/mvc/commons/RequestUtil.java | 64 +-- .../AbstractMethodInterceptor.java | 76 +--- .../plugin/tomcat10x/TomcatPluginConfig.java | 43 -- .../ApplicationDispatcherInstrumentation.java | 86 ---- .../define/TomcatInstrumentation.java | 100 ----- .../plugin/tomcat78x/ForwardInterceptor.java | 63 --- .../tomcat78x/TomcatExceptionInterceptor.java | 45 --- .../tomcat78x/TomcatInvokeInterceptor.java | 135 ------- .../pom.xml | 18 +- .../apm/plugin/tomcat}/Constants.java | 2 +- .../plugin/tomcat}/ForwardInterceptor.java | 2 +- .../tomcat}/TomcatExceptionInterceptor.java | 2 +- .../tomcat}/TomcatInvokeInterceptor.java | 21 +- .../plugin/tomcat}/TomcatPluginConfig.java | 2 +- .../ApplicationDispatcherInstrumentation.java | 9 +- .../tomcat}/define/TomcatInstrumentation.java | 13 +- .../src/main/resources/skywalking-plugin.def | 4 +- .../tomcat}/TomcatInvokeInterceptorTest.java | 16 +- .../org.mockito.plugins.MockMaker | 0 .../Java-Plugin-Development-Guide.md | 2 +- .../service-agent/java-agent/Plugin-list.md | 6 +- .../jersey-3.x-scenario/support-version.list | 2 +- .../jetty-11.x-scenario/support-version.list | 4 +- .../support-version.list | 2 +- .../resttemplate-6.x-scenario/bin/startup.sh | 2 +- .../config/expectedData.yaml | 4 + .../spring-6.x-scenario/configuration.yml | 4 +- .../spring-6.x-scenario/support-version.list | 2 +- .../spring-boot-2.x-scenario/bin/startup.sh | 21 + .../config/expectedData.yaml | 379 ++++++++++++++++++ .../configuration.yml | 22 + .../spring-boot-2.x-scenario/pom.xml | 114 ++++++ .../src/main/assembly/assembly.xml | 41 ++ .../skywalking/apm/testcase/Application.java | 23 +- .../skywalking/apm/testcase/entity/User.java | 53 +++ .../implinterface/TestCaseController.java | 35 ++ .../implinterface/TestCaseInterface.java | 31 ++ .../apm/testcase/inherit/ChildController.java | 28 ++ .../testcase/inherit/ParentController.java | 32 ++ .../testcase/restapi/RestCaseController.java | 77 ++++ .../resttemplate/RestTemplateController.java | 85 ++++ .../apm/testcase/spring3/CaseController.java | 41 ++ .../spring3/component/TestComponentBean.java | 29 ++ .../spring3/dao/TestRepositoryBean.java | 15 +- .../spring3/service/TestServiceBean.java | 38 ++ .../src/main/resources/application.yml | 6 +- .../src/main/resources/log4j2.xml | 30 ++ .../support-version.list | 11 +- .../spring-boot-3.x-scenario/bin/startup.sh | 21 + .../config/expectedData.yaml | 379 ++++++++++++++++++ .../configuration.yml | 22 + .../spring-boot-3.x-scenario/pom.xml | 125 ++++++ .../src/main/assembly/assembly.xml | 41 ++ .../skywalking/apm/testcase/Application.java | 30 ++ .../skywalking/apm/testcase/entity/User.java | 53 +++ .../implinterface/TestCaseController.java | 35 ++ .../implinterface/TestCaseInterface.java | 31 ++ .../apm/testcase/inherit/ChildController.java | 28 ++ .../testcase/inherit/ParentController.java | 32 ++ .../testcase/restapi/RestCaseController.java | 77 ++++ .../resttemplate/RestTemplateController.java | 85 ++++ .../apm/testcase/spring3/CaseController.java | 41 ++ .../spring3/component/TestComponentBean.java | 29 ++ .../spring3/dao/TestRepositoryBean.java | 15 +- .../spring3/service/TestServiceBean.java | 38 ++ .../src/main/resources/application.yml | 20 + .../src/main/resources/log4j2.xml | 30 ++ .../support-version.list | 22 + .../support-version.list | 5 +- 99 files changed, 2925 insertions(+), 1237 deletions(-) delete mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/ForwardInterceptor.java delete mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/AbstractWitnessInstrumentation.java delete mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml delete mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java delete mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/DispatcherInstrumentation.java delete mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/JettyInstrumentation.java rename apm-sniffer/apm-sdk-plugin/jetty-plugin/{jetty-server-11.x-plugin => jetty-server-plugin}/pom.xml (67%) rename apm-sniffer/apm-sdk-plugin/{tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x => jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server}/Constants.java (94%) rename apm-sniffer/apm-sdk-plugin/jetty-plugin/{jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9 => jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty}/server/ForwardInterceptor.java (97%) rename apm-sniffer/apm-sdk-plugin/jetty-plugin/{jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11 => jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty}/server/HandleInterceptor.java (75%) rename apm-sniffer/apm-sdk-plugin/jetty-plugin/{jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9 => jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty}/server/define/AbstractWitnessInstrumentation.java (75%) rename apm-sniffer/apm-sdk-plugin/jetty-plugin/{jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11 => jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty}/server/define/DispatcherInstrumentation.java (96%) rename apm-sniffer/apm-sdk-plugin/jetty-plugin/{jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11 => jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty}/server/define/JettyInstrumentation.java (96%) rename apm-sniffer/apm-sdk-plugin/{tomcat-10x-plugin => jetty-plugin/jetty-server-plugin}/src/main/resources/skywalking-plugin.def (81%) rename apm-sniffer/apm-sdk-plugin/jetty-plugin/{jetty-server-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9 => jetty-server-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty}/server/HandleInterceptorTest.java (89%) rename apm-sniffer/apm-sdk-plugin/{tomcat-7.x-8.x-plugin => servlet-commons}/pom.xml (50%) create mode 100644 apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrapper.java create mode 100644 apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrappers.java create mode 100644 apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrapper.java create mode 100644 apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrappers.java create mode 100644 apm-sniffer/apm-sdk-plugin/servlet-commons/src/test/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrappersTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/servlet-commons/src/test/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrappersTest.java delete mode 100644 apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrappers.java delete mode 100644 apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatPluginConfig.java delete mode 100644 apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/define/ApplicationDispatcherInstrumentation.java delete mode 100644 apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/define/TomcatInstrumentation.java delete mode 100644 apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/ForwardInterceptor.java delete mode 100644 apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatExceptionInterceptor.java delete mode 100644 apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java rename apm-sniffer/apm-sdk-plugin/{tomcat-10x-plugin => tomcat-plugin}/pom.xml (64%) rename apm-sniffer/apm-sdk-plugin/{tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x => tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat}/Constants.java (94%) rename apm-sniffer/apm-sdk-plugin/{tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x => tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat}/ForwardInterceptor.java (98%) rename apm-sniffer/apm-sdk-plugin/{tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x => tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat}/TomcatExceptionInterceptor.java (97%) rename apm-sniffer/apm-sdk-plugin/{tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x => tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat}/TomcatInvokeInterceptor.java (87%) rename apm-sniffer/apm-sdk-plugin/{tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x => tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat}/TomcatPluginConfig.java (97%) rename apm-sniffer/apm-sdk-plugin/{tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x => tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat}/define/ApplicationDispatcherInstrumentation.java (92%) rename apm-sniffer/apm-sdk-plugin/{tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x => tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat}/define/TomcatInstrumentation.java (91%) rename apm-sniffer/apm-sdk-plugin/{tomcat-7.x-8.x-plugin => tomcat-plugin}/src/main/resources/skywalking-plugin.def (80%) rename apm-sniffer/apm-sdk-plugin/{tomcat-7.x-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat78x => tomcat-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat}/TomcatInvokeInterceptorTest.java (90%) rename apm-sniffer/apm-sdk-plugin/{tomcat-7.x-8.x-plugin => tomcat-plugin}/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker (100%) create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/assembly/assembly.xml rename apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrapper.java => test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/Application.java (67%) create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.java create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java rename apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/Constants.java => test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java (71%) create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java rename apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/resources/skywalking-plugin.def => test/plugin/scenarios/spring-boot-2.x-scenario/src/main/resources/application.yml (80%) create mode 100644 test/plugin/scenarios/spring-boot-2.x-scenario/src/main/resources/log4j2.xml rename apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/resources/skywalking-plugin.def => test/plugin/scenarios/spring-boot-2.x-scenario/support-version.list (79%) create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/Application.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java rename apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/Constants.java => test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java (71%) create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/resources/application.yml create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/spring-boot-3.x-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index ed6efcfef4..6be997dc0e 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -71,6 +71,7 @@ jobs: matrix: case: - spring-6.x-scenario + - spring-boot-3.x-scenario - resteasy-6.x-scenario - gateway-4.x-scenario - gateway-4.1.2.x-scenario diff --git a/.github/workflows/plugins-test.2.yaml b/.github/workflows/plugins-test.2.yaml index 1bbf07ef31..042a14d947 100644 --- a/.github/workflows/plugins-test.2.yaml +++ b/.github/workflows/plugins-test.2.yaml @@ -74,6 +74,7 @@ jobs: - rabbitmq-scenario - redisson-scenario - resttemplate-4.x-scenario + - spring-boot-2.x-scenario - servicecomb-1.x-scenario - servicecomb-2.x-scenario - shardingsphere-3.x-scenario diff --git a/CHANGES.md b/CHANGES.md index 8136757432..9f994787ff 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,8 @@ Release Notes. 9.7.0 ------------------ +* Fix `plugin.http.include_http_headers` not working on Spring Boot 3.x / Jakarta EE (apache/skywalking#13938). +* Unify the Tomcat plugins into a single `tomcat` plugin (Tomcat 7 - 10) and the Jetty server plugins into a single `jetty-server` plugin (Jetty 9 - 11), each supporting both `javax.servlet` and `jakarta.servlet`. Breaking change: plugin names `tomcat-7.x/8.x` and `tomcat-10.x` are replaced by `tomcat`, and `jetty-server-9.x` and `jetty-server-11.x` by `jetty-server`; update `plugin.exclude_plugins` if you reference the old names. * Added support for Lettuce reactive Redis commands. * Add Spring AI 1.x plugin and GenAI layer. * Fix httpclient-5.x plugin injecting sw8 propagation headers into ClickHouse HTTP requests (port 8123), causing HTTP 400. Add `PROPAGATION_EXCLUDE_PORTS` config to skip tracing (including header injection) for specified ports in the classic client interceptor. diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/ForwardInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/ForwardInterceptor.java deleted file mode 100644 index f98e15c8af..0000000000 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/ForwardInterceptor.java +++ /dev/null @@ -1,63 +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.jetty.v11.server; - -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.InstanceConstructorInterceptor; -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 ForwardInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { - - @Override - public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { - if (ContextManager.isActive()) { - AbstractSpan abstractTracingSpan = ContextManager.activeSpan(); - Map eventMap = new HashMap(); - eventMap.put("forward-url", (String) objInst.getSkyWalkingDynamicField()); - abstractTracingSpan.log(System.currentTimeMillis(), eventMap); - ContextManager.getRuntimeContext().put(Constants.FORWARD_REQUEST_FLAG, true); - } - } - - @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) { - - } - - @Override - public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { - objInst.setSkyWalkingDynamicField(allArguments[2]); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/AbstractWitnessInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/AbstractWitnessInstrumentation.java deleted file mode 100644 index ae0eef39f3..0000000000 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/AbstractWitnessInstrumentation.java +++ /dev/null @@ -1,39 +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.jetty.v11.server.define; - -import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; - -import java.util.Collections; -import java.util.List; - -import static net.bytebuddy.matcher.ElementMatchers.named; -import static net.bytebuddy.matcher.ElementMatchers.takesArgument; - -public abstract class AbstractWitnessInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { - @Override - protected List witnessMethods() { - return Collections.singletonList(new WitnessMethod( - "org.eclipse.jetty.server.Handler", - named("handle").and(takesArgument(2, named("jakarta.servlet.http.HttpServletRequest"))) - )); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml deleted file mode 100644 index d4602b83c4..0000000000 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/pom.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - jetty-plugins - org.apache.skywalking - 9.7.0-SNAPSHOT - - 4.0.0 - - apm-jetty-server-9.x-plugin - jar - - jetty-server-9.x-plugin - http://maven.apache.org - - - 9.0.0.v20130308 - - - - - org.eclipse.jetty - jetty-server - ${jetty-server.version} - provided - - - diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java deleted file mode 100644 index 25006dd14c..0000000000 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java +++ /dev/null @@ -1,90 +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.jetty.v9.server; - -import java.lang.reflect.Method; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.apache.skywalking.apm.agent.core.context.CarrierItem; -import org.apache.skywalking.apm.agent.core.context.ContextCarrier; -import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.context.tag.Tags; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; -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.agent.core.util.MethodUtil; -import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; -import org.eclipse.jetty.server.HttpChannel; - -public class HandleInterceptor implements InstanceMethodsAroundInterceptor { - - private static boolean IS_SERVLET_GET_STATUS_METHOD_EXIST; - private static final String SERVLET_RESPONSE_CLASS = "javax.servlet.http.HttpServletResponse"; - private static final String GET_STATUS_METHOD = "getStatus"; - - static { - IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist(HandleInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); - } - - @Override - public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { - HttpChannel httpChannel = (HttpChannel) objInst; - HttpServletRequest servletRequest = httpChannel.getRequest(); - - ContextCarrier contextCarrier = new ContextCarrier(); - - CarrierItem next = contextCarrier.items(); - while (next.hasNext()) { - next = next.next(); - next.setHeadValue(servletRequest.getHeader(next.getHeadKey())); - } - - AbstractSpan span = ContextManager.createEntrySpan(servletRequest.getRequestURI(), contextCarrier); - Tags.URL.set(span, servletRequest.getRequestURL().toString()); - Tags.HTTP.METHOD.set(span, servletRequest.getMethod()); - span.setComponent(ComponentsDefine.JETTY_SERVER); - SpanLayer.asHttp(span); - } - - @Override - public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - Object ret) throws Throwable { - HttpChannel httpChannel = (HttpChannel) objInst; - HttpServletResponse servletResponse = httpChannel.getResponse(); - AbstractSpan span = ContextManager.activeSpan(); - if (IS_SERVLET_GET_STATUS_METHOD_EXIST) { - Tags.HTTP_RESPONSE_STATUS_CODE.set(span, servletResponse.getStatus()); - if (servletResponse.getStatus() >= 400) { - span.errorOccurred(); - } - } - ContextManager.stopSpan(); - ContextManager.getRuntimeContext().remove(Constants.FORWARD_REQUEST_FLAG); - return ret; - } - - @Override - public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t) { - ContextManager.activeSpan().log(t); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/DispatcherInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/DispatcherInstrumentation.java deleted file mode 100644 index 343e7d28c8..0000000000 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/DispatcherInstrumentation.java +++ /dev/null @@ -1,80 +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.jetty.v9.server.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.match.ClassMatch; - -import static net.bytebuddy.matcher.ElementMatchers.named; -import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; -import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; - -public class DispatcherInstrumentation extends AbstractWitnessInstrumentation { - - private static final String ENHANCE_CLASS = "org.eclipse.jetty.server.Dispatcher"; - public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.jetty.v9.server.ForwardInterceptor"; - - @Override - public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[]{ - new ConstructorInterceptPoint() { - @Override - public ElementMatcher getConstructorMatcher() { - return takesArgumentWithType(2, "java.lang.String"); - } - - @Override - public String getConstructorInterceptor() { - return INTERCEPT_CLASS; - } - } - }; - } - - @Override - public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{ - new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("forward"); - } - - @Override - public String getMethodsInterceptor() { - return INTERCEPT_CLASS; - } - - @Override - public boolean isOverrideArgs() { - return false; - } - } - }; - } - - @Override - protected ClassMatch enhanceClass() { - return byName(ENHANCE_CLASS); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/JettyInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/JettyInstrumentation.java deleted file mode 100644 index 59ac7307e6..0000000000 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/JettyInstrumentation.java +++ /dev/null @@ -1,71 +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.jetty.v9.server.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.match.ClassMatch; -import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch; - -import static net.bytebuddy.matcher.ElementMatchers.named; - -/** - * {@link JettyInstrumentation} enhance the handle method in org.eclipse.jetty.server.handler.HandlerList - * by HandleInterceptor - */ -public class JettyInstrumentation extends AbstractWitnessInstrumentation { - - private static final String ENHANCE_CLASS = "org.eclipse.jetty.server.HttpChannel"; - private static final String ENHANCE_METHOD = "handle"; - private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jetty.v9.server.HandleInterceptor"; - - @Override - public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[0]; - } - - @Override - public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{ - new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named(ENHANCE_METHOD); - } - - @Override - public String getMethodsInterceptor() { - return INTERCEPTOR_CLASS; - } - - @Override - public boolean isOverrideArgs() { - return false; - } - } - }; - } - - @Override - protected ClassMatch enhanceClass() { - return NameMatch.byName(ENHANCE_CLASS); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/pom.xml similarity index 67% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml rename to apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/pom.xml index c70f0ddd37..8477c1b9b8 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/pom.xml @@ -24,12 +24,19 @@ 4.0.0 - apm-jetty-server-11.x-plugin + apm-jetty-server-plugin jar - jetty-server-11.x-plugin + jetty-server-plugin http://maven.apache.org + 11.0.15 @@ -41,5 +48,11 @@ ${jetty-server.version} provided + + org.apache.skywalking + apm-servlet-commons + ${project.version} + provided + diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/Constants.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/Constants.java similarity index 94% rename from apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/Constants.java rename to apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/Constants.java index 64501083e1..22948d4a7d 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/Constants.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/Constants.java @@ -17,7 +17,7 @@ * */ -package org.apache.skywalking.apm.plugin.tomcat78x; +package org.apache.skywalking.apm.plugin.jetty.server; public class Constants { public static final String FORWARD_REQUEST_FLAG = "SW_FORWARD_REQUEST_FLAG"; diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/ForwardInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/ForwardInterceptor.java similarity index 97% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/ForwardInterceptor.java rename to apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/ForwardInterceptor.java index 669fae1770..0855f9961a 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/ForwardInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/ForwardInterceptor.java @@ -17,11 +17,8 @@ * */ -package org.apache.skywalking.apm.plugin.jetty.v9.server; +package org.apache.skywalking.apm.plugin.jetty.server; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; 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; @@ -29,6 +26,10 @@ 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 ForwardInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { @Override diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/HandleInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/HandleInterceptor.java similarity index 75% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/HandleInterceptor.java rename to apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/HandleInterceptor.java index a8f663a917..386587d270 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/HandleInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/HandleInterceptor.java @@ -16,10 +16,8 @@ * */ -package org.apache.skywalking.apm.plugin.jetty.v11.server; +package org.apache.skywalking.apm.plugin.jetty.server; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import org.apache.skywalking.apm.agent.core.context.CarrierItem; import org.apache.skywalking.apm.agent.core.context.ContextCarrier; import org.apache.skywalking.apm.agent.core.context.ContextManager; @@ -30,6 +28,10 @@ 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 org.apache.skywalking.apm.plugin.servlet.HttpRequestWrapper; +import org.apache.skywalking.apm.plugin.servlet.HttpRequestWrappers; +import org.apache.skywalking.apm.plugin.servlet.HttpResponseWrapper; +import org.apache.skywalking.apm.plugin.servlet.HttpResponseWrappers; import org.eclipse.jetty.server.HttpChannel; import java.lang.reflect.Method; @@ -40,7 +42,9 @@ public class HandleInterceptor implements InstanceMethodsAroundInterceptor { public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { HttpChannel httpChannel = (HttpChannel) objInst; - HttpServletRequest servletRequest = httpChannel.getRequest(); + // getRequest() returns the concrete org.eclipse.jetty.server.Request; the wrapper resolves the + // javax vs jakarta servlet namespace at runtime, keeping this interceptor namespace-neutral. + HttpRequestWrapper servletRequest = HttpRequestWrappers.wrap(httpChannel.getRequest()); ContextCarrier contextCarrier = new ContextCarrier(); @@ -61,11 +65,15 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { HttpChannel httpChannel = (HttpChannel) objInst; - HttpServletResponse servletResponse = httpChannel.getResponse(); AbstractSpan span = ContextManager.activeSpan(); - Tags.HTTP_RESPONSE_STATUS_CODE.set(span, servletResponse.getStatus()); - if (servletResponse.getStatus() >= 400) { - span.errorOccurred(); + // A null wrapper means getStatus() is unavailable (pre-Servlet-3.0), matching the historical guard. + HttpResponseWrapper servletResponse = HttpResponseWrappers.wrap(httpChannel.getResponse()); + if (servletResponse != null) { + int statusCode = servletResponse.getStatus(); + Tags.HTTP_RESPONSE_STATUS_CODE.set(span, statusCode); + if (statusCode >= 400) { + span.errorOccurred(); + } } ContextManager.stopSpan(); ContextManager.getRuntimeContext().remove(Constants.FORWARD_REQUEST_FLAG); diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/AbstractWitnessInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/define/AbstractWitnessInstrumentation.java similarity index 75% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/AbstractWitnessInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/define/AbstractWitnessInstrumentation.java index 9ed1aba497..3a0993fee7 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/define/AbstractWitnessInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/define/AbstractWitnessInstrumentation.java @@ -17,7 +17,7 @@ * */ -package org.apache.skywalking.apm.plugin.jetty.v9.server.define; +package org.apache.skywalking.apm.plugin.jetty.server.define; import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; @@ -31,9 +31,13 @@ public abstract class AbstractWitnessInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { @Override protected List witnessMethods() { + // Match the Jetty Handler#handle whose request argument is either the javax (Jetty 9/10) or the + // jakarta (Jetty 11) servlet namespace, so a single merged plugin activates on both. A single + // Jetty distribution carries only one namespace, so exactly one branch matches at runtime. return Collections.singletonList(new WitnessMethod( "org.eclipse.jetty.server.Handler", - named("handle").and(takesArgument(2, named("javax.servlet.http.HttpServletRequest"))) + named("handle").and(takesArgument(2, named("javax.servlet.http.HttpServletRequest") + .or(named("jakarta.servlet.http.HttpServletRequest")))) )); } } diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/DispatcherInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/define/DispatcherInstrumentation.java similarity index 96% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/DispatcherInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/define/DispatcherInstrumentation.java index d843ae629f..ba468ad1b3 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/DispatcherInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/define/DispatcherInstrumentation.java @@ -17,7 +17,7 @@ * */ -package org.apache.skywalking.apm.plugin.jetty.v11.server.define; +package org.apache.skywalking.apm.plugin.jetty.server.define; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -32,7 +32,7 @@ public class DispatcherInstrumentation extends AbstractWitnessInstrumentation { private static final String ENHANCE_CLASS = "org.eclipse.jetty.server.Dispatcher"; - public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.jetty.v11.server.ForwardInterceptor"; + public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.jetty.server.ForwardInterceptor"; @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/JettyInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/define/JettyInstrumentation.java similarity index 96% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/JettyInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/define/JettyInstrumentation.java index 417dc67df3..1c8eb083ac 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/define/JettyInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/server/define/JettyInstrumentation.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.jetty.v11.server.define; +package org.apache.skywalking.apm.plugin.jetty.server.define; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -35,7 +35,7 @@ public class JettyInstrumentation extends AbstractWitnessInstrumentation { private static final String ENHANCE_CLASS = "org.eclipse.jetty.server.HttpChannel"; private static final String ENHANCE_METHOD = "handle"; - private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jetty.v11.server" + + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.jetty.server" + ".HandleInterceptor"; @Override diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/resources/skywalking-plugin.def similarity index 81% rename from apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/resources/skywalking-plugin.def rename to apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/resources/skywalking-plugin.def index baa002ba28..f54cd54edb 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/main/resources/skywalking-plugin.def @@ -14,5 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -tomcat-10.x=org.apache.skywalking.apm.plugin.tomcat10x.define.TomcatInstrumentation -tomcat-10.x=org.apache.skywalking.apm.plugin.tomcat10x.define.ApplicationDispatcherInstrumentation +jetty-server=org.apache.skywalking.apm.plugin.jetty.server.define.JettyInstrumentation +jetty-server=org.apache.skywalking.apm.plugin.jetty.server.define.DispatcherInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/server/HandleInterceptorTest.java similarity index 89% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptorTest.java rename to apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/server/HandleInterceptorTest.java index f4c8fef0dd..77100bf9d0 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-plugin/src/test/java/org/apache/skywalking/apm/plugin/jetty/server/HandleInterceptorTest.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.jetty.v9.server; +package org.apache.skywalking.apm.plugin.jetty.server; import static org.apache.skywalking.apm.agent.test.tools.SpanAssert.assertComponent; import static org.hamcrest.CoreMatchers.is; @@ -44,7 +44,6 @@ import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpChannel; import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpInput; import org.eclipse.jetty.server.HttpTransport; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Response; @@ -87,6 +86,7 @@ public void setUp() throws Exception { jettyInvokeInterceptor = new HandleInterceptor(); when(request.getRequestURI()).thenReturn("/test/testRequestURL"); when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost:8080/test/testRequestURL")); + when(request.getMethod()).thenReturn("GET"); when(response.getStatus()).thenReturn(200); when(service.getResponse()).thenReturn(response); when(service.getRequest()).thenReturn(request); @@ -152,11 +152,18 @@ private void assertHttpSpan(AbstractTracingSpan span) { SpanAssert.assertLayer(span, SpanLayer.HTTP); } - public static class MockService extends HttpChannel implements EnhancedInstance { + /** + * The merged {@link HandleInterceptor} casts the enhanced instance to the concrete Jetty + * {@link HttpChannel} and reads the request/response through the servlet-commons wrappers, so the + * mock target must be a Jetty 11 (jakarta) {@link HttpChannel} whose {@link #getRequest()} / + * {@link #getResponse()} return jakarta servlet request/response objects. Declared abstract to + * skip Jetty 11 {@code HttpChannel}'s abstract members, which Mockito stubs automatically. + */ + public abstract static class MockService extends HttpChannel implements EnhancedInstance { public MockService(Connector connector, HttpConfiguration configuration, EndPoint endPoint, - HttpTransport transport, HttpInput input) { - super(connector, configuration, endPoint, transport, input); + HttpTransport transport) { + super(connector, configuration, endPoint, transport); } @Override diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml index 0d051bd4c0..1ac21fb14d 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml @@ -29,9 +29,8 @@ jetty-plugins jetty-client-9.x-plugin - jetty-server-9.x-plugin jetty-client-9.0-plugin - jetty-server-11.x-plugin + jetty-server-plugin jetty-client-11.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 5d09bd0957..829d63dd84 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -30,10 +30,10 @@ dubbo-plugin jdbc-commons + servlet-commons httpClient-4.x-plugin redisson-3.x-plugin - tomcat-7.x-8.x-plugin - tomcat-10x-plugin + tomcat-plugin motan-plugin mongodb-3.x-plugin mongodb-4.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servlet-commons/pom.xml similarity index 50% rename from apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml rename to apm-sniffer/apm-sdk-plugin/servlet-commons/pom.xml index 0763bcca65..55fc22ab3e 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/servlet-commons/pom.xml @@ -18,52 +18,57 @@ - apm-sdk-plugin org.apache.skywalking + apm-sdk-plugin 9.7.0-SNAPSHOT 4.0.0 - tomcat-7.x-8.x-plugin + apm-servlet-commons jar - tomcat-7.x-8.x-plugin - http://maven.apache.org + servlet-commons - 8.0.36 - 4.12 - 4.5.2 + 3.0.1 + 6.0.0 + - junit - junit - test - - - org.apache.tomcat.embed - tomcat-embed-core - ${tomcat.version} + javax.servlet + javax.servlet-api + ${javax-servlet-api.version} provided - org.apache.tomcat.embed - tomcat-embed-logging-juli - ${tomcat.version} - test + jakarta.servlet + jakarta.servlet-api + ${jakarta-servlet-api.version} + provided + - org.apache.tomcat.embed - tomcat-embed-jasper - ${tomcat.version} + junit + junit test - org.apache.httpcomponents - httpclient - ${apache-httpclient.version} + org.mockito + mockito-core test diff --git a/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrapper.java b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrapper.java new file mode 100644 index 0000000000..eee5d80dfe --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrapper.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.servlet; + +import java.util.Enumeration; +import java.util.Map; + +/** + * A namespace-agnostic view over a servlet HTTP request. It abstracts away the javax.servlet vs + * jakarta.servlet split so servlet plugin code can be written once. Obtain instances via + * {@link HttpRequestWrappers#wrap(Object)}. + *

+ * The method set is the union of what every servlet plugin actually reads; it intentionally does + * not expose cookies, sessions, multipart parts or the servlet context, none of which are collected. + */ +public interface HttpRequestWrapper { + + String getHeader(String name); + + Enumeration getHeaders(String name); + + String getMethod(); + + String getRequestURI(); + + StringBuffer getRequestURL(); + + String getRemoteHost(); + + Map getParameterMap(); +} diff --git a/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrappers.java b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrappers.java new file mode 100644 index 0000000000..6b35d9925b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrappers.java @@ -0,0 +1,158 @@ +/* + * 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.servlet; + +import java.util.Enumeration; +import java.util.Map; + +/** + * Factory producing a {@link HttpRequestWrapper} from either a {@code javax.servlet} or a + * {@code jakarta.servlet} {@code HttpServletRequest}, selected at runtime by the concrete type of + * the argument. Both servlet namespaces may be present on the classpath at once (e.g. a Jakarta + * application that also carries {@code javax.servlet-api} transitively); the flags below are + * computed independently so the live request type — not classpath presence order — decides. + *

+ * CLASSLOADING INVARIANT — DO NOT VIOLATE: every {@code javax}/{@code jakarta} reference lives + * inside its own nested wrapper class and is reached only through its {@link #IS_JAVAX} / + * {@link #IS_JAKARTA} flag guarded by a {@code &&} short-circuit. Never move a servlet type into + * {@link #wrap(Object)}'s shared body, never widen a method descriptor of this class to a servlet + * type, and never add a typed public {@code wrap(javax...)}/{@code wrap(jakarta...)} overload. Any + * of those makes the JVM eagerly resolve an absent namespace and reintroduces + * {@code NoClassDefFoundError} in single-namespace applications. Lazy constant-pool resolution + * keeps the guarded-but-unexecuted branch safe. + */ +public final class HttpRequestWrappers { + + private static final boolean IS_JAVAX = classExists("javax.servlet.http.HttpServletRequest"); + private static final boolean IS_JAKARTA = classExists("jakarta.servlet.http.HttpServletRequest"); + + private HttpRequestWrappers() { + } + + /** + * @param request any object; typically the servlet request captured by a plugin. + * @return a wrapper when {@code request} is a javax or jakarta {@code HttpServletRequest}, or + * {@code null} otherwise (e.g. a reactive request or an unrecognized type), letting the caller + * fall through to its own non-servlet handling. + */ + public static HttpRequestWrapper wrap(Object request) { + if (IS_JAVAX && request instanceof javax.servlet.http.HttpServletRequest) { + return new JavaxHttpServletRequest((javax.servlet.http.HttpServletRequest) request); + } + if (IS_JAKARTA && request instanceof jakarta.servlet.http.HttpServletRequest) { + return new JakartaHttpServletRequest((jakarta.servlet.http.HttpServletRequest) request); + } + return null; + } + + private static boolean classExists(String className) { + try { + Class.forName(className, false, HttpRequestWrappers.class.getClassLoader()); + return true; + } catch (Throwable ignore) { + return false; + } + } + + private static final class JavaxHttpServletRequest implements HttpRequestWrapper { + private final javax.servlet.http.HttpServletRequest request; + + private JavaxHttpServletRequest(javax.servlet.http.HttpServletRequest request) { + this.request = request; + } + + @Override + public String getHeader(String name) { + return request.getHeader(name); + } + + @Override + public Enumeration getHeaders(String name) { + return request.getHeaders(name); + } + + @Override + public String getMethod() { + return request.getMethod(); + } + + @Override + public String getRequestURI() { + return request.getRequestURI(); + } + + @Override + public StringBuffer getRequestURL() { + return request.getRequestURL(); + } + + @Override + public String getRemoteHost() { + return request.getRemoteHost(); + } + + @Override + public Map getParameterMap() { + return request.getParameterMap(); + } + } + + private static final class JakartaHttpServletRequest implements HttpRequestWrapper { + private final jakarta.servlet.http.HttpServletRequest request; + + private JakartaHttpServletRequest(jakarta.servlet.http.HttpServletRequest request) { + this.request = request; + } + + @Override + public String getHeader(String name) { + return request.getHeader(name); + } + + @Override + public Enumeration getHeaders(String name) { + return request.getHeaders(name); + } + + @Override + public String getMethod() { + return request.getMethod(); + } + + @Override + public String getRequestURI() { + return request.getRequestURI(); + } + + @Override + public StringBuffer getRequestURL() { + return request.getRequestURL(); + } + + @Override + public String getRemoteHost() { + return request.getRemoteHost(); + } + + @Override + public Map getParameterMap() { + return request.getParameterMap(); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrapper.java b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrapper.java new file mode 100644 index 0000000000..b31ded6456 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrapper.java @@ -0,0 +1,29 @@ +/* + * 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.servlet; + +/** + * A namespace-agnostic view over a servlet HTTP response. Obtain instances via + * {@link HttpResponseWrappers#wrap(Object)}. Only the response status code is exposed — the sole + * response datum servlet plugins collect. + */ +public interface HttpResponseWrapper { + + int getStatus(); +} diff --git a/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrappers.java b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrappers.java new file mode 100644 index 0000000000..4a85c44bac --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/main/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrappers.java @@ -0,0 +1,100 @@ +/* + * 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.servlet; + +/** + * Factory producing a {@link HttpResponseWrapper} from either a {@code javax.servlet} or a + * {@code jakarta.servlet} {@code HttpServletResponse}, selected at runtime. + *

+ * Detection deliberately checks that the {@code getStatus()} method exists (added in Servlet 3.0), + * not merely that the response class is present, preserving the guard for pre-3.0 containers where + * status is unavailable. {@link #servletStatusSupported()} lets a caller gate a non-servlet (e.g. + * reactive) status fallback on the same capability. + *

+ * The same CLASSLOADING INVARIANT as {@link HttpRequestWrappers} applies: keep every + * {@code javax}/{@code jakarta} reference inside its nested class behind its {@code &&}-guarded + * flag, and never widen this class's method descriptors to a servlet type. + */ +public final class HttpResponseWrappers { + + private static final boolean IS_JAVAX_STATUS = statusMethodExists("javax.servlet.http.HttpServletResponse"); + private static final boolean IS_JAKARTA_STATUS = statusMethodExists("jakarta.servlet.http.HttpServletResponse"); + + private HttpResponseWrappers() { + } + + /** + * @return {@code true} when a servlet {@code getStatus()} is available in either namespace. + */ + public static boolean servletStatusSupported() { + return IS_JAVAX_STATUS || IS_JAKARTA_STATUS; + } + + /** + * @param response any object; typically the servlet response captured by a plugin. + * @return a wrapper when {@code response} is a javax or jakarta {@code HttpServletResponse} that + * exposes {@code getStatus()}, or {@code null} otherwise (e.g. a reactive response), letting the + * caller fall through to its own handling. + */ + public static HttpResponseWrapper wrap(Object response) { + if (IS_JAVAX_STATUS && response instanceof javax.servlet.http.HttpServletResponse) { + return new JavaxHttpServletResponse((javax.servlet.http.HttpServletResponse) response); + } + if (IS_JAKARTA_STATUS && response instanceof jakarta.servlet.http.HttpServletResponse) { + return new JakartaHttpServletResponse((jakarta.servlet.http.HttpServletResponse) response); + } + return null; + } + + private static boolean statusMethodExists(String className) { + try { + Class clazz = Class.forName(className, false, HttpResponseWrappers.class.getClassLoader()); + clazz.getMethod("getStatus"); + return true; + } catch (Throwable ignore) { + return false; + } + } + + private static final class JavaxHttpServletResponse implements HttpResponseWrapper { + private final javax.servlet.http.HttpServletResponse response; + + private JavaxHttpServletResponse(javax.servlet.http.HttpServletResponse response) { + this.response = response; + } + + @Override + public int getStatus() { + return response.getStatus(); + } + } + + private static final class JakartaHttpServletResponse implements HttpResponseWrapper { + private final jakarta.servlet.http.HttpServletResponse response; + + private JakartaHttpServletResponse(jakarta.servlet.http.HttpServletResponse response) { + this.response = response; + } + + @Override + public int getStatus() { + return response.getStatus(); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/servlet-commons/src/test/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrappersTest.java b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/test/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrappersTest.java new file mode 100644 index 0000000000..87cd1a1a91 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/test/java/org/apache/skywalking/apm/plugin/servlet/HttpRequestWrappersTest.java @@ -0,0 +1,80 @@ +/* + * 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.servlet; + +import java.util.Collections; +import java.util.Enumeration; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Both javax.servlet-api and jakarta.servlet-api are on this module's test classpath, reproducing the + * exact apache/skywalking#13938 condition: both namespaces present at once. These tests assert that + * {@link HttpRequestWrappers#wrap(Object)} selects the wrapper matching the live request type rather + * than the classpath-presence order that the old exclusive detection got wrong. + */ +public class HttpRequestWrappersTest { + + @Test + public void wrapJakartaRequest() { + jakarta.servlet.http.HttpServletRequest request = mock(jakarta.servlet.http.HttpServletRequest.class); + when(request.getHeader("h")).thenReturn("v"); + when(request.getMethod()).thenReturn("GET"); + when(request.getRequestURI()).thenReturn("/uri"); + when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost/uri")); + when(request.getRemoteHost()).thenReturn("remote"); + when(request.getHeaders("h")).thenReturn(Collections.enumeration(Collections.singletonList("v"))); + + HttpRequestWrapper wrapper = HttpRequestWrappers.wrap(request); + + assertTrue(wrapper instanceof HttpRequestWrapper); + assertEquals("v", wrapper.getHeader("h")); + assertEquals("GET", wrapper.getMethod()); + assertEquals("/uri", wrapper.getRequestURI()); + assertEquals("http://localhost/uri", wrapper.getRequestURL().toString()); + assertEquals("remote", wrapper.getRemoteHost()); + Enumeration headers = wrapper.getHeaders("h"); + assertEquals("v", headers.nextElement()); + } + + @Test + public void wrapJavaxRequest() { + javax.servlet.http.HttpServletRequest request = mock(javax.servlet.http.HttpServletRequest.class); + when(request.getHeader("h")).thenReturn("v"); + when(request.getMethod()).thenReturn("POST"); + + HttpRequestWrapper wrapper = HttpRequestWrappers.wrap(request); + + assertTrue(wrapper instanceof HttpRequestWrapper); + assertEquals("v", wrapper.getHeader("h")); + assertEquals("POST", wrapper.getMethod()); + } + + @Test + public void wrapNonServletReturnsNull() { + assertNull(HttpRequestWrappers.wrap(new Object())); + assertNull(HttpRequestWrappers.wrap("not a request")); + assertNull(HttpRequestWrappers.wrap(null)); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/servlet-commons/src/test/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrappersTest.java b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/test/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrappersTest.java new file mode 100644 index 0000000000..c470a2c19b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/servlet-commons/src/test/java/org/apache/skywalking/apm/plugin/servlet/HttpResponseWrappersTest.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.servlet; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class HttpResponseWrappersTest { + + @Test + public void wrapJakartaResponse() { + jakarta.servlet.http.HttpServletResponse response = mock(jakarta.servlet.http.HttpServletResponse.class); + when(response.getStatus()).thenReturn(503); + + HttpResponseWrapper wrapper = HttpResponseWrappers.wrap(response); + + assertNotNull(wrapper); + assertEquals(503, wrapper.getStatus()); + } + + @Test + public void wrapJavaxResponse() { + javax.servlet.http.HttpServletResponse response = mock(javax.servlet.http.HttpServletResponse.class); + when(response.getStatus()).thenReturn(200); + + HttpResponseWrapper wrapper = HttpResponseWrappers.wrap(response); + + assertNotNull(wrapper); + assertEquals(200, wrapper.getStatus()); + } + + @Test + public void servletStatusSupportedWhenApiPresent() { + // Both servlet APIs (with getStatus, added in Servlet 3.0) are on the test classpath. + assertTrue(HttpResponseWrappers.servletStatusSupported()); + } + + @Test + public void wrapNonServletReturnsNull() { + assertNull(HttpResponseWrappers.wrap(new Object())); + assertNull(HttpResponseWrappers.wrap(null)); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml index f48ace4499..006febb79f 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/pom.xml @@ -61,5 +61,14 @@ ${project.version} provided + + + org.apache.skywalking + apm-servlet-commons + ${project.version} + provided + diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml index 65c554bb88..07bb6769f1 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/pom.xml @@ -55,16 +55,24 @@ 5.2.4.RELEASE provided + - javax.servlet - javax.servlet-api - ${javax-servlet-api.version} + org.apache.skywalking + apm-servlet-commons + ${project.version} provided - jakarta.servlet - jakarta.servlet-api - 6.0.0 + javax.servlet + javax.servlet-api + ${javax-servlet-api.version} provided diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrappers.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrappers.java deleted file mode 100644 index 663ad53c31..0000000000 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrappers.java +++ /dev/null @@ -1,112 +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.spring.mvc.commons; - -import java.util.Enumeration; -import java.util.Map; - -public class HttpServletRequestWrappers { - - public static HttpServletRequestWrapper wrap(jakarta.servlet.http.HttpServletRequest request) { - return new JakartaHttpServletRequest(request); - } - - public static HttpServletRequestWrapper wrap(javax.servlet.http.HttpServletRequest request) { - return new JavaxHttpServletRequest(request); - } - - public static class JakartaHttpServletRequest implements HttpServletRequestWrapper { - - private jakarta.servlet.http.HttpServletRequest jakartaRequest; - - public JakartaHttpServletRequest(jakarta.servlet.http.HttpServletRequest jakartaRequest) { - this.jakartaRequest = jakartaRequest; - } - - @Override - public String getHeader(String name) { - return jakartaRequest.getHeader(name); - } - - @Override - public String getMethod() { - return jakartaRequest.getMethod(); - } - - @Override - public StringBuffer getRequestURL() { - return jakartaRequest.getRequestURL(); - } - - @Override - public String getRemoteHost() { - return jakartaRequest.getRemoteHost(); - } - - @Override - public Map getParameterMap() { - return jakartaRequest.getParameterMap(); - } - - @Override - public Enumeration getHeaders(String name) { - return jakartaRequest.getHeaders(name); - } - - } - - public static class JavaxHttpServletRequest implements HttpServletRequestWrapper { - private javax.servlet.http.HttpServletRequest javaxRequest; - - public JavaxHttpServletRequest(javax.servlet.http.HttpServletRequest javaxRequest) { - this.javaxRequest = javaxRequest; - } - - @Override - public String getHeader(String name) { - return javaxRequest.getHeader(name); - } - - @Override - public String getMethod() { - return javaxRequest.getMethod(); - } - - @Override - public StringBuffer getRequestURL() { - return javaxRequest.getRequestURL(); - } - - @Override - public String getRemoteHost() { - return javaxRequest.getRemoteHost(); - } - - @Override - public Map getParameterMap() { - return javaxRequest.getParameterMap(); - } - - @Override - public Enumeration getHeaders(String name) { - return javaxRequest.getHeaders(name); - } - - } -} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java index f4f23b1c5b..f6cc0168d8 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java @@ -20,10 +20,10 @@ import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.util.CollectionUtil; +import org.apache.skywalking.apm.plugin.servlet.HttpRequestWrapper; import org.apache.skywalking.apm.util.StringUtil; import org.springframework.http.server.reactive.ServerHttpRequest; -import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; @@ -32,27 +32,7 @@ import java.util.Map; public class RequestUtil { - public static void collectHttpParam(HttpServletRequest request, AbstractSpan span) { - final Map parameterMap = request.getParameterMap(); - if (parameterMap != null && !parameterMap.isEmpty()) { - String tagValue = CollectionUtil.toString(parameterMap); - tagValue = SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? - StringUtil.cut(tagValue, SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue; - Tags.HTTP.PARAMS.set(span, tagValue); - } - } - - public static void collectHttpParam(jakarta.servlet.http.HttpServletRequest request, AbstractSpan span) { - final Map parameterMap = request.getParameterMap(); - if (parameterMap != null && !parameterMap.isEmpty()) { - String tagValue = CollectionUtil.toString(parameterMap); - tagValue = SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? - StringUtil.cut(tagValue, SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue; - Tags.HTTP.PARAMS.set(span, tagValue); - } - } - - public static void collectHttpParam(HttpServletRequestWrapper request, AbstractSpan span) { + public static void collectHttpParam(HttpRequestWrapper request, AbstractSpan span) { final Map parameterMap = request.getParameterMap(); if (parameterMap != null && !parameterMap.isEmpty()) { String tagValue = CollectionUtil.toString(parameterMap); @@ -75,45 +55,7 @@ public static void collectHttpParam(ServerHttpRequest request, AbstractSpan span } } - public static void collectHttpHeaders(HttpServletRequestWrapper request, AbstractSpan span) { - final List headersList = new ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size()); - SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream() - .filter( - headerName -> request.getHeaders(headerName) != null) - .forEach(headerName -> { - Enumeration headerValues = request.getHeaders( - headerName); - List valueList = Collections.list( - headerValues); - if (!CollectionUtil.isEmpty(valueList)) { - String headerValue = valueList.toString(); - headersList.add(headerName + "=" + headerValue); - } - }); - - collectHttpHeaders(headersList, span); - } - - public static void collectHttpHeaders(HttpServletRequest request, AbstractSpan span) { - final List headersList = new ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size()); - SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream() - .filter( - headerName -> request.getHeaders(headerName) != null) - .forEach(headerName -> { - Enumeration headerValues = request.getHeaders( - headerName); - List valueList = Collections.list( - headerValues); - if (!CollectionUtil.isEmpty(valueList)) { - String headerValue = valueList.toString(); - headersList.add(headerName + "=" + headerValue); - } - }); - - collectHttpHeaders(headersList, span); - } - - public static void collectHttpHeaders(jakarta.servlet.http.HttpServletRequest request, AbstractSpan span) { + public static void collectHttpHeaders(HttpRequestWrapper request, AbstractSpan span) { final List headersList = new ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size()); SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream() .filter( diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java index 67f2709c8f..8f70a71b3c 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java @@ -19,8 +19,6 @@ package org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor; import java.lang.reflect.Method; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.apache.skywalking.apm.agent.core.context.CarrierItem; import org.apache.skywalking.apm.agent.core.context.ContextCarrier; import org.apache.skywalking.apm.agent.core.context.ContextManager; @@ -36,9 +34,11 @@ import org.apache.skywalking.apm.agent.core.util.CollectionUtil; import org.apache.skywalking.apm.agent.core.util.MethodUtil; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.servlet.HttpRequestWrapper; +import org.apache.skywalking.apm.plugin.servlet.HttpRequestWrappers; +import org.apache.skywalking.apm.plugin.servlet.HttpResponseWrapper; +import org.apache.skywalking.apm.plugin.servlet.HttpResponseWrappers; import org.apache.skywalking.apm.plugin.spring.mvc.commons.EnhanceRequireObjectCache; -import org.apache.skywalking.apm.plugin.spring.mvc.commons.HttpServletRequestWrapper; -import org.apache.skywalking.apm.plugin.spring.mvc.commons.HttpServletRequestWrappers; import org.apache.skywalking.apm.plugin.spring.mvc.commons.RequestUtil; import org.apache.skywalking.apm.plugin.spring.mvc.commons.SpringMVCPluginConfig; import org.apache.skywalking.apm.plugin.spring.mvc.commons.exception.IllegalMethodStackDepthException; @@ -57,40 +57,6 @@ */ public abstract class AbstractMethodInterceptor implements InstanceMethodsAroundInterceptor { private static final ILog LOGGER = LogManager.getLogger(AbstractMethodInterceptor.class); - private static boolean IS_SERVLET_GET_STATUS_METHOD_EXIST; - private static boolean IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST; - private static final String SERVLET_RESPONSE_CLASS = "javax.servlet.http.HttpServletResponse"; - private static final String JAKARTA_SERVLET_RESPONSE_CLASS = "jakarta.servlet.http.HttpServletResponse"; - private static final String GET_STATUS_METHOD = "getStatus"; - - private static boolean IN_SERVLET_CONTAINER; - private static boolean IS_JAVAX = false; - private static boolean IS_JAKARTA = false; - - static { - IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist( - AbstractMethodInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); - IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist( - AbstractMethodInterceptor.class.getClassLoader(), - JAKARTA_SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD - ); - // Check both javax and jakarta independently — both may exist on the classpath. - // For example, a Spring MVC 6.x (Jakarta) app may have javax.servlet as a - // transitive dependency. The runtime request type determines which path is used. - try { - Class.forName(SERVLET_RESPONSE_CLASS, true, AbstractMethodInterceptor.class.getClassLoader()); - IS_JAVAX = true; - IN_SERVLET_CONTAINER = true; - } catch (Exception ignore) { - } - try { - Class.forName( - JAKARTA_SERVLET_RESPONSE_CLASS, true, AbstractMethodInterceptor.class.getClassLoader()); - IS_JAKARTA = true; - IN_SERVLET_CONTAINER = true; - } catch (Exception ignore) { - } - } public abstract String getRequestURL(Method method); @@ -115,16 +81,9 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr if (stackDepth == null) { final ContextCarrier contextCarrier = new ContextCarrier(); - if (IN_SERVLET_CONTAINER && IS_JAVAX && HttpServletRequest.class.isAssignableFrom(request.getClass())) { - final HttpServletRequest httpServletRequest = (HttpServletRequest) request; - handleBeforeMethod( - objInst, method, HttpServletRequestWrappers.wrap(httpServletRequest), contextCarrier); - - } else if (IN_SERVLET_CONTAINER && IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom( - request.getClass())) { - final jakarta.servlet.http.HttpServletRequest httpServletRequest = (jakarta.servlet.http.HttpServletRequest) request; - handleBeforeMethod( - objInst, method, HttpServletRequestWrappers.wrap(httpServletRequest), contextCarrier); + final HttpRequestWrapper httpServletRequest = HttpRequestWrappers.wrap(request); + if (httpServletRequest != null) { + handleBeforeMethod(objInst, method, httpServletRequest, contextCarrier); } else if (ServerHttpRequest.class.isAssignableFrom(request.getClass())) { final ServerHttpRequest serverHttpRequest = (ServerHttpRequest) request; @@ -167,7 +126,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } private void handleBeforeMethod(EnhancedInstance objInst, Method method, - HttpServletRequestWrapper httpServletRequest, ContextCarrier contextCarrier) { + HttpRequestWrapper httpServletRequest, ContextCarrier contextCarrier) { CarrierItem next = contextCarrier.items(); while (next.hasNext()) { next = next.next(); @@ -225,14 +184,11 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA Integer statusCode = null; - if (IS_SERVLET_GET_STATUS_METHOD_EXIST && HttpServletResponse.class.isAssignableFrom( - response.getClass())) { - statusCode = ((HttpServletResponse) response).getStatus(); - } else if (IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST && jakarta.servlet.http.HttpServletResponse.class.isAssignableFrom( - response.getClass())) { - statusCode = ((jakarta.servlet.http.HttpServletResponse) response).getStatus(); + final HttpResponseWrapper httpServletResponse = HttpResponseWrappers.wrap(response); + if (httpServletResponse != null) { + statusCode = httpServletResponse.getStatus(); } else if (ServerHttpResponse.class.isAssignableFrom(response.getClass())) { - if (IS_SERVLET_GET_STATUS_METHOD_EXIST || IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST) { + if (HttpResponseWrappers.servletStatusSupported()) { statusCode = ((ServerHttpResponse) response).getRawStatusCode(); } Object context = runtimeContext.get(REACTIVE_ASYNC_SPAN_IN_RUNTIME_CONTEXT); @@ -256,11 +212,9 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA // Active HTTP parameter collection automatically in the profiling context. if (!SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS && span.isProfiling()) { - if (IS_JAVAX && HttpServletRequest.class.isAssignableFrom(request.getClass())) { - RequestUtil.collectHttpParam((HttpServletRequest) request, span); - } else if (IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom( - request.getClass())) { - RequestUtil.collectHttpParam((jakarta.servlet.http.HttpServletRequest) request, span); + final HttpRequestWrapper httpServletRequest = HttpRequestWrappers.wrap(request); + if (httpServletRequest != null) { + RequestUtil.collectHttpParam(httpServletRequest, span); } else if (ServerHttpRequest.class.isAssignableFrom(request.getClass())) { RequestUtil.collectHttpParam((ServerHttpRequest) request, span); } diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatPluginConfig.java b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatPluginConfig.java deleted file mode 100644 index 2c2865d63a..0000000000 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatPluginConfig.java +++ /dev/null @@ -1,43 +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.tomcat10x; - -import org.apache.skywalking.apm.agent.core.boot.PluginConfig; - -public class TomcatPluginConfig { - public static class Plugin { - @PluginConfig(root = TomcatPluginConfig.class) - public static class Tomcat { - /** - * This config item controls that whether the Tomcat plugin should collect the parameters of the request. - */ - public static boolean COLLECT_HTTP_PARAMS = false; - } - - @PluginConfig(root = TomcatPluginConfig.class) - public static class Http { - /** - * When either {@link Tomcat#COLLECT_HTTP_PARAMS} is enabled, how many characters to keep and send to the - * OAP backend, use negative values to keep and send the complete parameters, NB. this config item is added - * for the sake of performance - */ - public static int HTTP_PARAMS_LENGTH_THRESHOLD = 1024; - } - } -} diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/define/ApplicationDispatcherInstrumentation.java b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/define/ApplicationDispatcherInstrumentation.java deleted file mode 100644 index 048ee28f38..0000000000 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/define/ApplicationDispatcherInstrumentation.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.tomcat10x.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.any; -import static net.bytebuddy.matcher.ElementMatchers.named; -import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; - -public class ApplicationDispatcherInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { - - private static final String ENHANCE_CLASS = "org.apache.catalina.core.ApplicationDispatcher"; - private static final String ENHANCE_METHOD = "forward"; - public static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.tomcat10x.ForwardInterceptor"; - - @Override - protected String[] witnessClasses() { - return new String[]{"jakarta.servlet.http.HttpServletResponse"}; - } - - @Override - public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[] { - new ConstructorInterceptPoint() { - @Override - public ElementMatcher getConstructorMatcher() { - return any(); - } - - @Override - public String getConstructorInterceptor() { - return INTERCEPTOR_CLASS; - } - } - }; - } - - @Override - public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[] { - new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named(ENHANCE_METHOD); - } - - @Override - public String getMethodsInterceptor() { - return INTERCEPTOR_CLASS; - } - - @Override - public boolean isOverrideArgs() { - return false; - } - } - }; - } - - @Override - protected ClassMatch enhanceClass() { - return byName(ENHANCE_CLASS); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/define/TomcatInstrumentation.java b/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/define/TomcatInstrumentation.java deleted file mode 100644 index 0ba3356a1d..0000000000 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/define/TomcatInstrumentation.java +++ /dev/null @@ -1,100 +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.tomcat10x.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 org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; - -public class TomcatInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { - - /** - * Enhance class. - */ - private static final String ENHANCE_CLASS = "org.apache.catalina.core.StandardHostValve"; - - /** - * The intercept class for "invoke" method in the class "org.apache.catalina.core.StandardHostValve" - */ - private static final String INVOKE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.tomcat10x.TomcatInvokeInterceptor"; - - /** - * The intercept class for "exception" method in the class "org.apache.catalina.core.StandardHostValve" - */ - private static final String EXCEPTION_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.tomcat10x.TomcatExceptionInterceptor"; - - @Override - protected String[] witnessClasses() { - return new String[]{"jakarta.servlet.http.HttpServletResponse"}; - } - - @Override - protected ClassMatch enhanceClass() { - return byName(ENHANCE_CLASS); - } - - @Override - public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return null; - } - - @Override - public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[] { - new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("invoke"); - } - - @Override - public String getMethodsInterceptor() { - return INVOKE_INTERCEPT_CLASS; - } - - @Override - public boolean isOverrideArgs() { - return false; - } - }, - new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("throwable"); - } - - @Override - public String getMethodsInterceptor() { - return EXCEPTION_INTERCEPT_CLASS; - } - - @Override - public boolean isOverrideArgs() { - return false; - } - } - }; - } -} diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/ForwardInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/ForwardInterceptor.java deleted file mode 100644 index ab43e22fb3..0000000000 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/ForwardInterceptor.java +++ /dev/null @@ -1,63 +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.tomcat78x; - -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; -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.InstanceConstructorInterceptor; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; - -public class ForwardInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { - - @Override - public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { - if (ContextManager.isActive()) { - AbstractSpan abstractTracingSpan = ContextManager.activeSpan(); - Map eventMap = new HashMap(); - eventMap.put("forward-url", objInst.getSkyWalkingDynamicField() == null ? "" : String.valueOf(objInst.getSkyWalkingDynamicField())); - abstractTracingSpan.log(System.currentTimeMillis(), eventMap); - ContextManager.getRuntimeContext().put(Constants.FORWARD_REQUEST_FLAG, true); - } - } - - @Override - public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - Object ret) throws Throwable { - ContextManager.getRuntimeContext().remove(Constants.FORWARD_REQUEST_FLAG); - return ret; - } - - @Override - public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t) { - - } - - @Override - public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { - objInst.setSkyWalkingDynamicField(allArguments[1]); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatExceptionInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatExceptionInterceptor.java deleted file mode 100644 index 28c8a9a20a..0000000000 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatExceptionInterceptor.java +++ /dev/null @@ -1,45 +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.tomcat78x; - -import java.lang.reflect.Method; -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; - -public class TomcatExceptionInterceptor implements InstanceMethodsAroundInterceptor { - @Override - public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { - ContextManager.activeSpan().log((Throwable) allArguments[2]); - } - - @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) { - - } -} diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java deleted file mode 100644 index 29004e6e46..0000000000 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java +++ /dev/null @@ -1,135 +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.tomcat78x; - -import java.lang.reflect.Method; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.apache.catalina.connector.Request; -import org.apache.skywalking.apm.agent.core.context.CarrierItem; -import org.apache.skywalking.apm.agent.core.context.ContextCarrier; -import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.context.tag.Tags; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; -import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; -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.agent.core.util.CollectionUtil; -import org.apache.skywalking.apm.agent.core.util.MethodUtil; -import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; -import org.apache.skywalking.apm.util.StringUtil; -import org.apache.tomcat.util.http.Parameters; - -/** - * {@link TomcatInvokeInterceptor} fetch the serialized context data by using {@link - * HttpServletRequest#getHeader(String)}. The {@link TraceSegment#ref} of current trace segment will reference to the - * trace segment id of the previous level if the serialized context is not null. - */ -public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor { - - private static boolean IS_SERVLET_GET_STATUS_METHOD_EXIST; - private static final String SERVLET_RESPONSE_CLASS = "javax.servlet.http.HttpServletResponse"; - private static final String GET_STATUS_METHOD = "getStatus"; - - static { - IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist( - TomcatInvokeInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); - } - - /** - * * The {@link TraceSegment#ref} of current trace segment will reference to the trace segment id of the previous - * level if the serialized context is not null. - * - * @param result change this result, if you want to truncate the method. - */ - @Override - public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { - Request request = (Request) allArguments[0]; - ContextCarrier contextCarrier = new ContextCarrier(); - - CarrierItem next = contextCarrier.items(); - while (next.hasNext()) { - next = next.next(); - next.setHeadValue(request.getHeader(next.getHeadKey())); - } - String operationName = String.join(":", request.getMethod(), request.getRequestURI()); - AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier); - Tags.URL.set(span, request.getRequestURL().toString()); - Tags.HTTP.METHOD.set(span, request.getMethod()); - span.setComponent(ComponentsDefine.TOMCAT); - SpanLayer.asHttp(span); - - if (TomcatPluginConfig.Plugin.Tomcat.COLLECT_HTTP_PARAMS) { - collectHttpParam(request, span); - } - } - - @Override - public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - Object ret) throws Throwable { - Request request = (Request) allArguments[0]; - HttpServletResponse response = (HttpServletResponse) allArguments[1]; - - AbstractSpan span = ContextManager.activeSpan(); - if (IS_SERVLET_GET_STATUS_METHOD_EXIST) { - Tags.HTTP_RESPONSE_STATUS_CODE.set(span, response.getStatus()); - if (response.getStatus() >= 400) { - span.errorOccurred(); - } - } - // Active HTTP parameter collection automatically in the profiling context. - if (!TomcatPluginConfig.Plugin.Tomcat.COLLECT_HTTP_PARAMS && span.isProfiling()) { - collectHttpParam(request, span); - } - ContextManager.getRuntimeContext().remove(Constants.FORWARD_REQUEST_FLAG); - ContextManager.stopSpan(); - return ret; - } - - @Override - public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t) { - AbstractSpan span = ContextManager.activeSpan(); - span.log(t); - } - - private void collectHttpParam(Request request, AbstractSpan span) { - final Map parameterMap = new HashMap<>(); - final org.apache.coyote.Request coyoteRequest = request.getCoyoteRequest(); - final Parameters parameters = coyoteRequest.getParameters(); - for (final Enumeration names = parameters.getParameterNames(); names.hasMoreElements(); ) { - final String name = names.nextElement(); - parameterMap.put(name, parameters.getParameterValues(name)); - } - - if (!parameterMap.isEmpty()) { - String tagValue = CollectionUtil.toString(parameterMap); - tagValue = TomcatPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ? - StringUtil.cut(tagValue, TomcatPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : - tagValue; - Tags.HTTP.PARAMS.set(span, tagValue); - } - } -} diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/pom.xml similarity index 64% rename from apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/pom.xml index 7c54849e28..d0b23363e1 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/pom.xml @@ -25,8 +25,18 @@ 4.0.0 - tomcat-10x-plugin + apm-tomcat-plugin + tomcat-plugin + + 10.0.22 @@ -37,6 +47,12 @@ ${tomcat.version} provided + + org.apache.skywalking + apm-servlet-commons + ${project.version} + provided + diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/Constants.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/Constants.java similarity index 94% rename from apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/Constants.java rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/Constants.java index 3aa2d92ae3..9f783d15c0 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/Constants.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/Constants.java @@ -17,7 +17,7 @@ * */ -package org.apache.skywalking.apm.plugin.tomcat10x; +package org.apache.skywalking.apm.plugin.tomcat; public class Constants { public static final String FORWARD_REQUEST_FLAG = "SW_FORWARD_REQUEST_FLAG"; diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/ForwardInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/ForwardInterceptor.java similarity index 98% rename from apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/ForwardInterceptor.java rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/ForwardInterceptor.java index 8c64a1d0a9..6f48059390 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/ForwardInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/ForwardInterceptor.java @@ -17,7 +17,7 @@ * */ -package org.apache.skywalking.apm.plugin.tomcat10x; +package org.apache.skywalking.apm.plugin.tomcat; import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatExceptionInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatExceptionInterceptor.java similarity index 97% rename from apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatExceptionInterceptor.java rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatExceptionInterceptor.java index ac9ba9f61e..ab854aa554 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatExceptionInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatExceptionInterceptor.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.tomcat10x; +package org.apache.skywalking.apm.plugin.tomcat; import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatInvokeInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptor.java similarity index 87% rename from apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatInvokeInterceptor.java rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptor.java index 52bedf994d..9cb009199a 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-10x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat10x/TomcatInvokeInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptor.java @@ -16,9 +16,8 @@ * */ -package org.apache.skywalking.apm.plugin.tomcat10x; +package org.apache.skywalking.apm.plugin.tomcat; -import jakarta.servlet.http.HttpServletResponse; import org.apache.catalina.connector.Request; import org.apache.skywalking.apm.agent.core.context.CarrierItem; import org.apache.skywalking.apm.agent.core.context.ContextCarrier; @@ -32,6 +31,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.agent.core.util.CollectionUtil; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.servlet.HttpResponseWrapper; +import org.apache.skywalking.apm.plugin.servlet.HttpResponseWrappers; import org.apache.skywalking.apm.util.StringUtil; import org.apache.tomcat.util.http.Parameters; @@ -42,9 +43,6 @@ public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor { - private static final String SERVLET_RESPONSE_CLASS = "jakarta.servlet.http.HttpServletResponse"; - private static final String GET_STATUS_METHOD = "getStatus"; - @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { @@ -72,12 +70,17 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { Request request = (Request) allArguments[0]; - HttpServletResponse response = (HttpServletResponse) allArguments[1]; AbstractSpan span = ContextManager.activeSpan(); - Tags.HTTP_RESPONSE_STATUS_CODE.set(span, response.getStatus()); - if (response.getStatus() >= 400) { - span.errorOccurred(); + // The response status is read through the namespace-agnostic wrapper; it returns null when + // getStatus() is unavailable (pre-Servlet-3.0), preserving the historical guard behavior. + HttpResponseWrapper response = HttpResponseWrappers.wrap(allArguments[1]); + if (response != null) { + int statusCode = response.getStatus(); + Tags.HTTP_RESPONSE_STATUS_CODE.set(span, statusCode); + if (statusCode >= 400) { + span.errorOccurred(); + } } // Active HTTP parameter collection automatically in the profiling context. if (!TomcatPluginConfig.Plugin.Tomcat.COLLECT_HTTP_PARAMS && span.isProfiling()) { diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatPluginConfig.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatPluginConfig.java similarity index 97% rename from apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatPluginConfig.java rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatPluginConfig.java index 4bc6174d73..0a1d713cf9 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatPluginConfig.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatPluginConfig.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.tomcat78x; +package org.apache.skywalking.apm.plugin.tomcat; import org.apache.skywalking.apm.agent.core.boot.PluginConfig; diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/define/ApplicationDispatcherInstrumentation.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/define/ApplicationDispatcherInstrumentation.java similarity index 92% rename from apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/define/ApplicationDispatcherInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/define/ApplicationDispatcherInstrumentation.java index 14158594fa..f1d8f0370d 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/define/ApplicationDispatcherInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/define/ApplicationDispatcherInstrumentation.java @@ -16,7 +16,7 @@ * */ -package org.apache.skywalking.apm.plugin.tomcat78x.define; +package org.apache.skywalking.apm.plugin.tomcat.define; import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -33,12 +33,7 @@ public class ApplicationDispatcherInstrumentation extends ClassInstanceMethodsEn private static final String ENHANCE_CLASS = "org.apache.catalina.core.ApplicationDispatcher"; private static final String ENHANCE_METHOD = "forward"; - public static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.tomcat78x.ForwardInterceptor"; - - @Override - protected String[] witnessClasses() { - return new String[]{"javax.servlet.http.HttpServletResponse"}; - } + public static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.tomcat.ForwardInterceptor"; @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/define/TomcatInstrumentation.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/define/TomcatInstrumentation.java similarity index 91% rename from apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/define/TomcatInstrumentation.java rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/define/TomcatInstrumentation.java index ffcae42fe8..67e9a4296d 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/define/TomcatInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/define/TomcatInstrumentation.java @@ -16,13 +16,13 @@ * */ -package org.apache.skywalking.apm.plugin.tomcat78x.define; +package org.apache.skywalking.apm.plugin.tomcat.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.interceptor.ConstructorInterceptPoint; import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -38,17 +38,12 @@ public class TomcatInstrumentation extends ClassInstanceMethodsEnhancePluginDefi /** * The intercept class for "invoke" method in the class "org.apache.catalina.core.StandardHostValve" */ - private static final String INVOKE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.tomcat78x.TomcatInvokeInterceptor"; + private static final String INVOKE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.tomcat.TomcatInvokeInterceptor"; /** * The intercept class for "exception" method in the class "org.apache.catalina.core.StandardHostValve" */ - private static final String EXCEPTION_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.tomcat78x.TomcatExceptionInterceptor"; - - @Override - protected String[] witnessClasses() { - return new String[]{"javax.servlet.http.HttpServletResponse"}; - } + private static final String EXCEPTION_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.tomcat.TomcatExceptionInterceptor"; @Override protected ClassMatch enhanceClass() { diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/resources/skywalking-plugin.def similarity index 80% rename from apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/resources/skywalking-plugin.def index 761d3970d3..35eb529458 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/resources/skywalking-plugin.def @@ -14,5 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -tomcat-7.x/8.x=org.apache.skywalking.apm.plugin.tomcat78x.define.TomcatInstrumentation -tomcat-7.x/8.x=org.apache.skywalking.apm.plugin.tomcat78x.define.ApplicationDispatcherInstrumentation +tomcat=org.apache.skywalking.apm.plugin.tomcat.define.TomcatInstrumentation +tomcat=org.apache.skywalking.apm.plugin.tomcat.define.ApplicationDispatcherInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptorTest.java similarity index 90% rename from apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptorTest.java rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptorTest.java index 4aeb68c89a..b3fe9b9022 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptorTest.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/test/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptorTest.java @@ -16,15 +16,15 @@ * */ -package org.apache.skywalking.apm.plugin.tomcat78x; +package org.apache.skywalking.apm.plugin.tomcat; import static org.apache.skywalking.apm.agent.test.tools.SpanAssert.assertComponent; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.Mockito.when; import java.util.List; -import javax.servlet.http.HttpServletResponse; import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; import org.apache.skywalking.apm.agent.core.context.SW8CarrierItem; import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; import org.apache.skywalking.apm.agent.core.context.trace.LogDataEntity; @@ -65,8 +65,14 @@ public class TomcatInvokeInterceptorTest { @Mock private Request request; + /** + * The merged tomcat-plugin compiles against tomcat-embed-core 10.0.22, whose Catalina + * {@link Response} implements {@code jakarta.servlet.http.HttpServletResponse}. The interceptor + * reads the status through {@code HttpResponseWrappers.wrap(response).getStatus()}, which selects + * the jakarta branch for this mock and returns the stubbed status below. + */ @Mock - private HttpServletResponse response; + private Response response; @Mock private MethodInterceptResult methodInterceptResult; @@ -177,6 +183,10 @@ private void assertHttpSpan(AbstractTracingSpan span) { assertThat(span.getOperationName(), is("GET:/test/testRequestURL")); assertComponent(span, ComponentsDefine.TOMCAT); SpanAssert.assertTag(span, 0, "http://localhost:8080/test/testRequestURL"); + // The status read via HttpResponseWrappers.wrap(response).getStatus() is recorded as the + // http.status_code tag; the original tomcat78x test omitted this assertion. + assertThat(SpanHelper.getTags(span).get(2).getKey().key(), is("http.status_code")); + SpanAssert.assertTag(span, 2, "200"); assertThat(span.isEntry(), is(true)); SpanAssert.assertLayer(span, SpanLayer.HTTP); } diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker similarity index 100% rename from apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker rename to apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md index 201835a1dc..c581000ea5 100644 --- a/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md +++ b/docs/en/setup/service-agent/java-agent/Java-Plugin-Development-Guide.md @@ -360,7 +360,7 @@ The following sections will tell you how to implement the interceptor. 3. Add plugin definition into the `skywalking-plugin.def` file. ```properties -tomcat-7.x/8.x=TomcatInstrumentation +tomcat=TomcatInstrumentation ``` 4. Set up `witnessClasses` and/or `witnessMethods` if the instrumentation has to be activated in specific versions. 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 ed16dc1f85..2e5ad78336 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -55,7 +55,7 @@ - jedis-4.x - jetty-client-9.0 - jetty-client-9.x -- jetty-server-9.x +- jetty-server - kafka-0.11.x/1.x/2.x - kafka-3.7.x - kafka-3.9.x @@ -133,8 +133,7 @@ - spymemcached-2.x - struts2-2.x - thrift -- tomcat-7.x/8.x -- tomcat-10.x +- tomcat - toolkit-counter - toolkit-gauge - toolkit-histogram @@ -180,7 +179,6 @@ - jersey-3.x - grizzly-2.3.x-4.x - grizzly-2.3.x-4.x-threadpool -- jetty-server-11.x - jetty-client-11.x - websphere-liberty-23.x - spring-cloud-gateway-4.x diff --git a/test/plugin/scenarios/jersey-3.x-scenario/support-version.list b/test/plugin/scenarios/jersey-3.x-scenario/support-version.list index bf93530913..ac6d65588a 100644 --- a/test/plugin/scenarios/jersey-3.x-scenario/support-version.list +++ b/test/plugin/scenarios/jersey-3.x-scenario/support-version.list @@ -15,4 +15,4 @@ # limitations under the License. 3.0.0 -3.1.1 +3.1.12 diff --git a/test/plugin/scenarios/jetty-11.x-scenario/support-version.list b/test/plugin/scenarios/jetty-11.x-scenario/support-version.list index 140bec1629..ad7671ecf9 100644 --- a/test/plugin/scenarios/jetty-11.x-scenario/support-version.list +++ b/test/plugin/scenarios/jetty-11.x-scenario/support-version.list @@ -14,6 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -11.0.0 -11.0.7 -11.0.15 +11.0.26 diff --git a/test/plugin/scenarios/resteasy-6.x-scenario/support-version.list b/test/plugin/scenarios/resteasy-6.x-scenario/support-version.list index 49ada0d6d6..9b953ddf82 100644 --- a/test/plugin/scenarios/resteasy-6.x-scenario/support-version.list +++ b/test/plugin/scenarios/resteasy-6.x-scenario/support-version.list @@ -15,6 +15,6 @@ # limitations under the License. # test all 6.x version, with corresponding latest patch version -6.2.4.Final +6.2.16.Final 6.1.0.Final 6.0.3.Final \ No newline at end of file diff --git a/test/plugin/scenarios/resttemplate-6.x-scenario/bin/startup.sh b/test/plugin/scenarios/resttemplate-6.x-scenario/bin/startup.sh index 197feca45a..bd736d21e8 100644 --- a/test/plugin/scenarios/resttemplate-6.x-scenario/bin/startup.sh +++ b/test/plugin/scenarios/resttemplate-6.x-scenario/bin/startup.sh @@ -18,6 +18,6 @@ home="$(cd "$(dirname $0)"; pwd)" -export SW_EXCLUDE_PLUGINS=spring-mvc-annotation,spring-mvc-annotation-3.x,spring-mvc-annotation-4.x,spring-mvc-annotation-5.x,spring-resttemplate-4.x,tomcat-7.x/8.x,tomcat-10.x +export SW_EXCLUDE_PLUGINS=spring-mvc-annotation,spring-mvc-annotation-3.x,spring-mvc-annotation-4.x,spring-mvc-annotation-5.x,spring-resttemplate-4.x,tomcat java -jar ${agent_opts} ${home}/../libs/resttemplate-6.x-scenario.jar & diff --git a/test/plugin/scenarios/spring-6.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-6.x-scenario/config/expectedData.yaml index 926a3f2b4c..081211529f 100644 --- a/test/plugin/scenarios/spring-6.x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/spring-6.x-scenario/config/expectedData.yaml @@ -371,5 +371,9 @@ segmentItems: tags: - {key: url, value: 'http://localhost:8080/spring-6.x-scenario/case/resttemplate'} - {key: http.method, value: GET} + - key: http.params + value: |- + q1=[v1] + chinese=[中文] - {key: http.status_code, value: '200'} skipAnalysis: 'false' diff --git a/test/plugin/scenarios/spring-6.x-scenario/configuration.yml b/test/plugin/scenarios/spring-6.x-scenario/configuration.yml index 4e81ad6a99..bb658f8656 100644 --- a/test/plugin/scenarios/spring-6.x-scenario/configuration.yml +++ b/test/plugin/scenarios/spring-6.x-scenario/configuration.yml @@ -15,9 +15,9 @@ # limitations under the License. type: tomcat -entryService: http://localhost:8080/spring-6.x-scenario/case/resttemplate +entryService: '"http://localhost:8080/spring-6.x-scenario/case/resttemplate?q1=v1&chinese=%e4%b8%ad%e6%96%87"' healthCheck: http://localhost:8080/spring-6.x-scenario/healthCheck runningMode: with_optional withPlugins: apm-spring-annotation-plugin-*.jar;apm-*-6.x-plugin-*.jar environment: - - CATALINA_OPTS="-Dskywalking.plugin.http.include_http_headers=mock_header" + - CATALINA_OPTS="-Dskywalking.plugin.http.include_http_headers=mock_header -Dskywalking.plugin.springmvc.collect_http_params=true" diff --git a/test/plugin/scenarios/spring-6.x-scenario/support-version.list b/test/plugin/scenarios/spring-6.x-scenario/support-version.list index c96f0b4304..947a86b2f5 100644 --- a/test/plugin/scenarios/spring-6.x-scenario/support-version.list +++ b/test/plugin/scenarios/spring-6.x-scenario/support-version.list @@ -15,5 +15,5 @@ # limitations under the License. 6.0.4 -6.1.0 6.1.1 +6.2.19 diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/bin/startup.sh b/test/plugin/scenarios/spring-boot-2.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..cc7c8bd115 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-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 -Dskywalking.plugin.http.include_http_headers=mock_header -Dskywalking.plugin.springmvc.collect_http_params=true -jar ${agent_opts} ${home}/../libs/spring-boot-2.x-scenario.jar & diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-boot-2.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..a0c9365bd2 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/config/expectedData.yaml @@ -0,0 +1,379 @@ +# 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: spring-boot-2.x-scenario + segmentSize: ge 10 + segments: + - segmentId: not null + spans: + - operationName: HEAD:/healthCheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/healthCheck'} + - {key: http.method, value: HEAD} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: test.apache.skywalking.apm.testcase.spring3.component.TestComponentBean.componentMethod + parentSpanId: 1 + spanId: 2 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 93 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: test.apache.skywalking.apm.testcase.spring3.dao.TestRepositoryBean.doSomeStuff + parentSpanId: 1 + spanId: 3 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 93 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: test.apache.skywalking.apm.testcase.spring3.service.TestServiceBean.doSomeBusiness + parentSpanId: 0 + spanId: 1 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 93 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: GET:/case/spring3 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/case/spring3'} + - {key: http.method, value: GET} + - {key: http.headers, value: 'mock_header=[mock_value]'} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-2.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'POST:/create/' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/create/'} + - {key: http.method, value: POST} + - {key: http.status_code, value: '201'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-2.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'GET:/get/{id}' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/get/1'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 3, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-2.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'PUT:/update/{id}' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/update/1'} + - {key: http.method, value: PUT} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 4, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-2.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'DELETE:/delete/{id}' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/delete/1'} + - {key: http.method, value: DELETE} + - {key: http.status_code, value: '204'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 5, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-2.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GET:/inherit/child/test + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/inherit/child/test'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 6, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-2.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GET:/impl/requestmapping + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/impl/requestmapping'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 7, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-2.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'GET:/impl/restmapping' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/impl/restmapping'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 8, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-2.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: /spring-boot-2.x-scenario/case/spring3 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/case/spring3'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-2.x-scenario/create/ + parentSpanId: 0 + spanId: 2 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/create/'} + - {key: http.method, value: POST} + - {key: http.status_code, value: '201'} + skipAnalysis: 'false' + - operationName: /spring-boot-2.x-scenario/get/1 + parentSpanId: 0 + spanId: 3 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/get/1'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-2.x-scenario/update/1 + parentSpanId: 0 + spanId: 4 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/update/1'} + - {key: http.method, value: PUT} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-2.x-scenario/delete/1 + parentSpanId: 0 + spanId: 5 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/delete/1'} + - {key: http.method, value: DELETE} + - {key: http.status_code, value: '204'} + skipAnalysis: 'false' + - operationName: /spring-boot-2.x-scenario/inherit/child/test + parentSpanId: 0 + spanId: 6 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/inherit/child/test'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-2.x-scenario/impl/requestmapping + parentSpanId: 0 + spanId: 7 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/impl/requestmapping'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-2.x-scenario/impl/restmapping + parentSpanId: 0 + spanId: 8 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/impl/restmapping'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: GET:/case/resttemplate + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-2.x-scenario/case/resttemplate'} + - {key: http.method, value: GET} + - key: http.params + value: |- + q1=[v1] + chinese=[中文] + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/configuration.yml b/test/plugin/scenarios/spring-boot-2.x-scenario/configuration.yml new file mode 100644 index 0000000000..e698f0affb --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-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/spring-boot-2.x-scenario/case/resttemplate?q1=v1&chinese=%e4%b8%ad%e6%96%87"' +healthCheck: http://localhost:8080/spring-boot-2.x-scenario/healthCheck +startScript: ./bin/startup.sh +runningMode: with_optional +withPlugins: apm-spring-annotation-plugin-*.jar diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/pom.xml b/test/plugin/scenarios/spring-boot-2.x-scenario/pom.xml new file mode 100644 index 0000000000..e2b3b867a5 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + org.apache.skywalking + spring-boot-2.x-scenario + 5.0.0 + + jar + + + UTF-8 + UTF-8 + 8 + 3.11.0 + + 2.7.18 + spring-boot + + + skywalking-spring-boot-2.x-scenario + + + + + org.springframework.boot + spring-boot-starter-web + ${test.framework.version} + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + ${test.framework.version} + + + + com.squareup.okhttp3 + okhttp + 4.10.0 + + + + + spring-boot-2.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${test.framework.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + true + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..c255ce5f79 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ./target/spring-boot-2.x-scenario.jar + ./libs + 0775 + + + diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrapper.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/Application.java similarity index 67% rename from apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrapper.java rename to test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/Application.java index d258f7a5f2..bdb91531cc 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/HttpServletRequestWrapper.java +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/Application.java @@ -16,22 +16,15 @@ * */ -package org.apache.skywalking.apm.plugin.spring.mvc.commons; +package test.apache.skywalking.apm.testcase; -import java.util.Enumeration; -import java.util.Map; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; -public interface HttpServletRequestWrapper { +@SpringBootApplication +public class Application { - String getHeader(String name); - - String getMethod(); - - StringBuffer getRequestURL(); - - String getRemoteHost(); - - Map getParameterMap(); - - public Enumeration getHeaders(String name); + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } } diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.java new file mode 100644 index 0000000000..e7fb1871e5 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.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 test.apache.skywalking.apm.testcase.entity; + +public class User { + + private int id; + private String userName; + + public User(int id) { + this.id = id; + } + + public User(int id, String userName) { + this.id = id; + this.userName = userName; + } + + public User() { + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java new file mode 100644 index 0000000000..7a95a9318a --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java @@ -0,0 +1,35 @@ +/* + * 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.implinterface; + +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestCaseController implements TestCaseInterface { + + @Override + public String implRequestMappingAnnotationTestCase() { + return "implRequestMappingAnnotationTestCase"; + } + + @Override + public String implRestAnnotationTestCase() { + return "implRestAnnotationTestCase"; + } +} diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java new file mode 100644 index 0000000000..4fea97b7b1 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java @@ -0,0 +1,31 @@ +/* + * 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.implinterface; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@RequestMapping("/impl") +public interface TestCaseInterface { + @RequestMapping(path = "/requestmapping") + String implRequestMappingAnnotationTestCase(); + + @GetMapping("/restmapping") + String implRestAnnotationTestCase(); +} diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java new file mode 100644 index 0000000000..27ddf54c76 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java @@ -0,0 +1,28 @@ +/* + * 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.inherit; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/inherit/child") +public class ChildController extends ParentController { + +} diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java new file mode 100644 index 0000000000..16b928100d --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java @@ -0,0 +1,32 @@ +/* + * 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.inherit; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/inherit/parent") +public class ParentController { + + @RequestMapping("test") + public String test(Integer param) { + return "parent-a" + param; + } +} diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java new file mode 100644 index 0000000000..6792ecb712 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java @@ -0,0 +1,77 @@ +/* + * 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.restapi; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.util.UriComponentsBuilder; +import test.apache.skywalking.apm.testcase.entity.User; + +@RestController +public class RestCaseController { + + private static final Map USERS = new ConcurrentHashMap(); + + @GetMapping(value = "/get/{id}") + @ResponseBody + private ResponseEntity getUser(@PathVariable("id") int id) throws InterruptedException { + User currentUser = new User(id, "a"); + return ResponseEntity.ok(currentUser); + } + + @PostMapping(value = "/create/") + @ResponseBody + public ResponseEntity createUser(@RequestBody User user, + UriComponentsBuilder ucBuilder) throws InterruptedException { + USERS.put(user.getId(), user); + HttpHeaders headers = new HttpHeaders(); + headers.setLocation(ucBuilder.path("/get/{id}").buildAndExpand(user.getId()).toUri()); + return new ResponseEntity(headers, HttpStatus.CREATED); + } + + @PutMapping(value = "/update/{id}") + @ResponseBody + public ResponseEntity updateUser(@PathVariable("id") int id, + @RequestBody User user) throws InterruptedException { + User currentUser = new User(id, user.getUserName()); + return ResponseEntity.ok(currentUser); + } + + @DeleteMapping(value = "/delete/{id}") + @ResponseBody + public ResponseEntity deleteUser(@PathVariable("id") int id) throws InterruptedException { + User currentUser = USERS.get(id); + if (currentUser == null) { + return ResponseEntity.noContent().build(); + } + USERS.remove(id); + return ResponseEntity.noContent().build(); + } +} diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java new file mode 100644 index 0000000000..ba80f261b0 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java @@ -0,0 +1,85 @@ +/* + * 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.resttemplate; + +import java.io.IOException; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.http.HttpEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; +import test.apache.skywalking.apm.testcase.entity.User; + +@RestController +public class RestTemplateController { + + private static final String SUCCESS = "Success"; + + private static final Logger LOGGER = LogManager.getLogger(RestTemplateController.class); + + private static final String URL = "http://localhost:8080/spring-boot-2.x-scenario"; + + @RequestMapping("/case/resttemplate") + @ResponseBody + public String restTemplate() throws IOException { + Request request = new Request.Builder().header("mock_header", "mock_value").url(URL + "/case/spring3").build(); + Response response = new OkHttpClient().newCall(request).execute(); + LOGGER.info(response.toString()); + + // Create user + HttpEntity userEntity = new HttpEntity<>(new User(1, "a")); + new RestTemplate().postForEntity(URL + "/create/", userEntity, Void.class); + + // Find User + new RestTemplate().getForEntity(URL + "/get/{id}", User.class, 1); + + //Modify user + HttpEntity updateUserEntity = new HttpEntity<>(new User(1, "b")); + new RestTemplate().put(URL + "/update/{id}", updateUserEntity, userEntity.getBody().getId(), 1); + + //Delete user + new RestTemplate().delete(URL + "/delete/{id}", 1); + + Request inheritRequest = new Request.Builder().url(URL + "/inherit/child/test").build(); + response = new OkHttpClient().newCall(inheritRequest).execute(); + LOGGER.info(response.toString()); + + Request implRequestMappingRequest = new Request.Builder().url(URL + "/impl/requestmapping").build(); + response = new OkHttpClient().newCall(implRequestMappingRequest).execute(); + LOGGER.info(response.toString()); + + Request implRestMappingRequest = new Request.Builder().url(URL + "/impl/restmapping").build(); + response = new OkHttpClient().newCall(implRestMappingRequest).execute(); + LOGGER.info(response.toString()); + + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java new file mode 100644 index 0000000000..501c691579 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java @@ -0,0 +1,41 @@ +/* + * 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.spring3; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import test.apache.skywalking.apm.testcase.spring3.service.TestServiceBean; + +@Controller +public class CaseController { + + private static final String SUCCESS = "Success"; + + @Autowired + private TestServiceBean testServiceBean; + + @RequestMapping(value = "/case/spring3") + @ResponseBody + public String updateUser() { + testServiceBean.doSomeBusiness("test"); + return SUCCESS; + } +} diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java new file mode 100644 index 0000000000..274aaf490e --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java @@ -0,0 +1,29 @@ +/* + * 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.spring3.component; + +import org.springframework.stereotype.Component; + +@Component +public class TestComponentBean { + + public String componentMethod(String name) { + return name + "-" + "dealWith-component"; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/Constants.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java similarity index 71% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/Constants.java rename to test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java index 156bb0517b..84f871ef55 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v11/server/Constants.java +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java @@ -6,7 +6,7 @@ * (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 + * 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, @@ -14,11 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * */ -package org.apache.skywalking.apm.plugin.jetty.v11.server; +package test.apache.skywalking.apm.testcase.spring3.dao; + +import org.springframework.stereotype.Repository; + +@Repository +public class TestRepositoryBean { -public class Constants { - public static final String FORWARD_REQUEST_FLAG = "SW_FORWARD_REQUEST_FLAG"; + public String doSomeStuff(String name) { + return name + "-dealWithRepository"; + } } diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java new file mode 100644 index 0000000000..811fe11648 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java @@ -0,0 +1,38 @@ +/* + * 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.spring3.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import test.apache.skywalking.apm.testcase.spring3.dao.TestRepositoryBean; +import test.apache.skywalking.apm.testcase.spring3.component.TestComponentBean; + +@Service +public class TestServiceBean { + @Autowired + private TestComponentBean componentBean; + + @Autowired + private TestRepositoryBean repositoryBean; + + public void doSomeBusiness(String name) { + componentBean.componentMethod(name); + repositoryBean.doSomeStuff(name); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/resources/skywalking-plugin.def b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/resources/application.yml similarity index 80% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/resources/skywalking-plugin.def rename to test/plugin/scenarios/spring-boot-2.x-scenario/src/main/resources/application.yml index 915c014315..e92dacba1a 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/resources/skywalking-plugin.def +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/resources/application.yml @@ -14,5 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -jetty-server-9.x=org.apache.skywalking.apm.plugin.jetty.v9.server.define.JettyInstrumentation -jetty-server-9.x=org.apache.skywalking.apm.plugin.jetty.v9.server.define.DispatcherInstrumentation +server: + port: 8080 + servlet: + context-path: /spring-boot-2.x-scenario diff --git a/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..b5cda5ae8a --- /dev/null +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/resources/skywalking-plugin.def b/test/plugin/scenarios/spring-boot-2.x-scenario/support-version.list similarity index 79% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/resources/skywalking-plugin.def rename to test/plugin/scenarios/spring-boot-2.x-scenario/support-version.list index a7828a8f4b..a1e6762600 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-11.x-plugin/src/main/resources/skywalking-plugin.def +++ b/test/plugin/scenarios/spring-boot-2.x-scenario/support-version.list @@ -14,5 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -jetty-server-11.x=org.apache.skywalking.apm.plugin.jetty.v11.server.define.JettyInstrumentation -jetty-server-11.x=org.apache.skywalking.apm.plugin.jetty.v11.server.define.DispatcherInstrumentation +# Spring Boot 2.x -> embedded Tomcat 9 (javax) + Spring MVC 5, one per minor (latest patch) +2.0.9.RELEASE +2.1.18.RELEASE +2.2.13.RELEASE +2.3.12.RELEASE +2.4.13 +2.5.15 +2.6.15 +2.7.18 diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/bin/startup.sh b/test/plugin/scenarios/spring-boot-3.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..c72984e26c --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-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 -Dskywalking.plugin.http.include_http_headers=mock_header -Dskywalking.plugin.springmvc.collect_http_params=true -jar ${agent_opts} ${home}/../libs/spring-boot-3.x-scenario.jar & diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-boot-3.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..a80d126128 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/config/expectedData.yaml @@ -0,0 +1,379 @@ +# 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: spring-boot-3.x-scenario + segmentSize: ge 10 + segments: + - segmentId: not null + spans: + - operationName: HEAD:/healthCheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/healthCheck'} + - {key: http.method, value: HEAD} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: test.apache.skywalking.apm.testcase.spring3.component.TestComponentBean.componentMethod + parentSpanId: 1 + spanId: 2 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 93 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: test.apache.skywalking.apm.testcase.spring3.dao.TestRepositoryBean.doSomeStuff + parentSpanId: 1 + spanId: 3 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 93 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: test.apache.skywalking.apm.testcase.spring3.service.TestServiceBean.doSomeBusiness + parentSpanId: 0 + spanId: 1 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 93 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: GET:/case/spring3 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/case/spring3'} + - {key: http.method, value: GET} + - {key: http.headers, value: 'mock_header=[mock_value]'} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'POST:/create/' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/create/'} + - {key: http.method, value: POST} + - {key: http.status_code, value: '201'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'GET:/get/{id}' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/get/1'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 3, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'PUT:/update/{id}' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/update/1'} + - {key: http.method, value: PUT} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 4, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'DELETE:/delete/{id}' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/delete/1'} + - {key: http.method, value: DELETE} + - {key: http.status_code, value: '204'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 5, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GET:/inherit/child/test + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/inherit/child/test'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 6, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GET:/impl/requestmapping + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/impl/requestmapping'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 7, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'GET:/impl/restmapping' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/impl/restmapping'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 8, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-boot-3.x-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: /spring-boot-3.x-scenario/case/spring3 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/case/spring3'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-3.x-scenario/create/ + parentSpanId: 0 + spanId: 2 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/create/'} + - {key: http.method, value: POST} + - {key: http.status_code, value: '201'} + skipAnalysis: 'false' + - operationName: /spring-boot-3.x-scenario/get/1 + parentSpanId: 0 + spanId: 3 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/get/1'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-3.x-scenario/update/1 + parentSpanId: 0 + spanId: 4 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/update/1'} + - {key: http.method, value: PUT} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-3.x-scenario/delete/1 + parentSpanId: 0 + spanId: 5 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/delete/1'} + - {key: http.method, value: DELETE} + - {key: http.status_code, value: '204'} + skipAnalysis: 'false' + - operationName: /spring-boot-3.x-scenario/inherit/child/test + parentSpanId: 0 + spanId: 6 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/inherit/child/test'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-3.x-scenario/impl/requestmapping + parentSpanId: 0 + spanId: 7 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/impl/requestmapping'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-boot-3.x-scenario/impl/restmapping + parentSpanId: 0 + spanId: 8 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/impl/restmapping'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: GET:/case/resttemplate + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-boot-3.x-scenario/case/resttemplate'} + - {key: http.method, value: GET} + - key: http.params + value: |- + q1=[v1] + chinese=[中文] + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/configuration.yml b/test/plugin/scenarios/spring-boot-3.x-scenario/configuration.yml new file mode 100644 index 0000000000..0263142980 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-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/spring-boot-3.x-scenario/case/resttemplate?q1=v1&chinese=%e4%b8%ad%e6%96%87"' +healthCheck: http://localhost:8080/spring-boot-3.x-scenario/healthCheck +startScript: ./bin/startup.sh +runningMode: with_optional +withPlugins: apm-spring-annotation-plugin-*.jar;apm-*-6.x-plugin-*.jar diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/pom.xml b/test/plugin/scenarios/spring-boot-3.x-scenario/pom.xml new file mode 100644 index 0000000000..3f9bddf53d --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/pom.xml @@ -0,0 +1,125 @@ + + + + 4.0.0 + + org.apache.skywalking + spring-boot-3.x-scenario + 5.0.0 + + jar + + + UTF-8 + UTF-8 + 17 + 3.11.0 + + 3.5.16 + spring-boot + + + skywalking-spring-boot-3.x-scenario + + + + + org.springframework.boot + spring-boot-starter-web + ${test.framework.version} + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + ${test.framework.version} + + + + com.squareup.okhttp3 + okhttp + 4.10.0 + + + + + spring-boot-3.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${test.framework.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + true + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + + + + spring-snapshots + https://repo.spring.io/snapshot + + + spring-milestones + https://repo.spring.io/milestone + + + diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..fcd1eab0d8 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ./target/spring-boot-3.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/Application.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/Application.java new file mode 100644 index 0000000000..bdb91531cc --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/Application.java @@ -0,0 +1,30 @@ +/* + * 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; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.java new file mode 100644 index 0000000000..e7fb1871e5 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.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 test.apache.skywalking.apm.testcase.entity; + +public class User { + + private int id; + private String userName; + + public User(int id) { + this.id = id; + } + + public User(int id, String userName) { + this.id = id; + this.userName = userName; + } + + public User() { + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java new file mode 100644 index 0000000000..7a95a9318a --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java @@ -0,0 +1,35 @@ +/* + * 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.implinterface; + +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestCaseController implements TestCaseInterface { + + @Override + public String implRequestMappingAnnotationTestCase() { + return "implRequestMappingAnnotationTestCase"; + } + + @Override + public String implRestAnnotationTestCase() { + return "implRestAnnotationTestCase"; + } +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java new file mode 100644 index 0000000000..4fea97b7b1 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java @@ -0,0 +1,31 @@ +/* + * 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.implinterface; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@RequestMapping("/impl") +public interface TestCaseInterface { + @RequestMapping(path = "/requestmapping") + String implRequestMappingAnnotationTestCase(); + + @GetMapping("/restmapping") + String implRestAnnotationTestCase(); +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java new file mode 100644 index 0000000000..27ddf54c76 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java @@ -0,0 +1,28 @@ +/* + * 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.inherit; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/inherit/child") +public class ChildController extends ParentController { + +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java new file mode 100644 index 0000000000..16b928100d --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java @@ -0,0 +1,32 @@ +/* + * 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.inherit; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/inherit/parent") +public class ParentController { + + @RequestMapping("test") + public String test(Integer param) { + return "parent-a" + param; + } +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java new file mode 100644 index 0000000000..6792ecb712 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java @@ -0,0 +1,77 @@ +/* + * 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.restapi; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.util.UriComponentsBuilder; +import test.apache.skywalking.apm.testcase.entity.User; + +@RestController +public class RestCaseController { + + private static final Map USERS = new ConcurrentHashMap(); + + @GetMapping(value = "/get/{id}") + @ResponseBody + private ResponseEntity getUser(@PathVariable("id") int id) throws InterruptedException { + User currentUser = new User(id, "a"); + return ResponseEntity.ok(currentUser); + } + + @PostMapping(value = "/create/") + @ResponseBody + public ResponseEntity createUser(@RequestBody User user, + UriComponentsBuilder ucBuilder) throws InterruptedException { + USERS.put(user.getId(), user); + HttpHeaders headers = new HttpHeaders(); + headers.setLocation(ucBuilder.path("/get/{id}").buildAndExpand(user.getId()).toUri()); + return new ResponseEntity(headers, HttpStatus.CREATED); + } + + @PutMapping(value = "/update/{id}") + @ResponseBody + public ResponseEntity updateUser(@PathVariable("id") int id, + @RequestBody User user) throws InterruptedException { + User currentUser = new User(id, user.getUserName()); + return ResponseEntity.ok(currentUser); + } + + @DeleteMapping(value = "/delete/{id}") + @ResponseBody + public ResponseEntity deleteUser(@PathVariable("id") int id) throws InterruptedException { + User currentUser = USERS.get(id); + if (currentUser == null) { + return ResponseEntity.noContent().build(); + } + USERS.remove(id); + return ResponseEntity.noContent().build(); + } +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java new file mode 100644 index 0000000000..89947c72d6 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java @@ -0,0 +1,85 @@ +/* + * 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.resttemplate; + +import java.io.IOException; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.http.HttpEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; +import test.apache.skywalking.apm.testcase.entity.User; + +@RestController +public class RestTemplateController { + + private static final String SUCCESS = "Success"; + + private static final Logger LOGGER = LogManager.getLogger(RestTemplateController.class); + + private static final String URL = "http://localhost:8080/spring-boot-3.x-scenario"; + + @RequestMapping("/case/resttemplate") + @ResponseBody + public String restTemplate() throws IOException { + Request request = new Request.Builder().header("mock_header", "mock_value").url(URL + "/case/spring3").build(); + Response response = new OkHttpClient().newCall(request).execute(); + LOGGER.info(response.toString()); + + // Create user + HttpEntity userEntity = new HttpEntity<>(new User(1, "a")); + new RestTemplate().postForEntity(URL + "/create/", userEntity, Void.class); + + // Find User + new RestTemplate().getForEntity(URL + "/get/{id}", User.class, 1); + + //Modify user + HttpEntity updateUserEntity = new HttpEntity<>(new User(1, "b")); + new RestTemplate().put(URL + "/update/{id}", updateUserEntity, userEntity.getBody().getId(), 1); + + //Delete user + new RestTemplate().delete(URL + "/delete/{id}", 1); + + Request inheritRequest = new Request.Builder().url(URL + "/inherit/child/test").build(); + response = new OkHttpClient().newCall(inheritRequest).execute(); + LOGGER.info(response.toString()); + + Request implRequestMappingRequest = new Request.Builder().url(URL + "/impl/requestmapping").build(); + response = new OkHttpClient().newCall(implRequestMappingRequest).execute(); + LOGGER.info(response.toString()); + + Request implRestMappingRequest = new Request.Builder().url(URL + "/impl/restmapping").build(); + response = new OkHttpClient().newCall(implRestMappingRequest).execute(); + LOGGER.info(response.toString()); + + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java new file mode 100644 index 0000000000..501c691579 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java @@ -0,0 +1,41 @@ +/* + * 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.spring3; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import test.apache.skywalking.apm.testcase.spring3.service.TestServiceBean; + +@Controller +public class CaseController { + + private static final String SUCCESS = "Success"; + + @Autowired + private TestServiceBean testServiceBean; + + @RequestMapping(value = "/case/spring3") + @ResponseBody + public String updateUser() { + testServiceBean.doSomeBusiness("test"); + return SUCCESS; + } +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java new file mode 100644 index 0000000000..274aaf490e --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java @@ -0,0 +1,29 @@ +/* + * 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.spring3.component; + +import org.springframework.stereotype.Component; + +@Component +public class TestComponentBean { + + public String componentMethod(String name) { + return name + "-" + "dealWith-component"; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/Constants.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java similarity index 71% rename from apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/Constants.java rename to test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java index e1e8d84d65..84f871ef55 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/Constants.java +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java @@ -6,7 +6,7 @@ * (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 + * 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, @@ -14,11 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * */ -package org.apache.skywalking.apm.plugin.jetty.v9.server; +package test.apache.skywalking.apm.testcase.spring3.dao; + +import org.springframework.stereotype.Repository; + +@Repository +public class TestRepositoryBean { -public class Constants { - public static final String FORWARD_REQUEST_FLAG = "SW_FORWARD_REQUEST_FLAG"; + public String doSomeStuff(String name) { + return name + "-dealWithRepository"; + } } diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java new file mode 100644 index 0000000000..811fe11648 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java @@ -0,0 +1,38 @@ +/* + * 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.spring3.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import test.apache.skywalking.apm.testcase.spring3.dao.TestRepositoryBean; +import test.apache.skywalking.apm.testcase.spring3.component.TestComponentBean; + +@Service +public class TestServiceBean { + @Autowired + private TestComponentBean componentBean; + + @Autowired + private TestRepositoryBean repositoryBean; + + public void doSomeBusiness(String name) { + componentBean.componentMethod(name); + repositoryBean.doSomeStuff(name); + } +} diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/resources/application.yml b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/resources/application.yml new file mode 100644 index 0000000000..e67ba613ef --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/resources/application.yml @@ -0,0 +1,20 @@ +# 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 + servlet: + context-path: /spring-boot-3.x-scenario diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..b5cda5ae8a --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/test/plugin/scenarios/spring-boot-3.x-scenario/support-version.list b/test/plugin/scenarios/spring-boot-3.x-scenario/support-version.list new file mode 100644 index 0000000000..1f8df5c9b3 --- /dev/null +++ b/test/plugin/scenarios/spring-boot-3.x-scenario/support-version.list @@ -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. + +3.0.13 +3.1.12 +3.2.12 +3.3.13 +3.4.13 +3.5.16 diff --git a/test/plugin/scenarios/undertow-2.3.x-scenario/support-version.list b/test/plugin/scenarios/undertow-2.3.x-scenario/support-version.list index a3dca1ddcf..1f4d4b5614 100644 --- a/test/plugin/scenarios/undertow-2.3.x-scenario/support-version.list +++ b/test/plugin/scenarios/undertow-2.3.x-scenario/support-version.list @@ -14,5 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Undertow 2.3.x requires Java 11+, tested with JDK 17 -2.3.18.Final +# Undertow 2.3.x requires Java 11+; 2.4.x requires Java 17. Tested with JDK 17. +2.3.25.Final +2.4.2.Final From 64035d609a9f5d3bf0ff74eac190a74c0b5cd26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Tue, 7 Jul 2026 11:21:52 +0800 Subject: [PATCH 113/114] Add Jetty 12 and Struts 7 (Jakarta) agent plugins (#813) Jetty 12 removed the concrete HttpChannel whose handle() the merged jetty-server plugin enhances, and moved request handling to the async, namespace-neutral core API Server#handle(Request, Response, Callback). Add a separate jetty-server-12.x plugin that enhances it and records an async entry span (finished with the response status when the wrapped Callback completes). Struts 7 relocated DefaultActionInvocation from com.opensymphony.xwork2 to org.apache.struts2 and switched to jakarta.servlet. Add a struts2-7.x plugin enhancing the new class (a distinct package from struts2-2.x avoids collision). Both reuse existing components (JettyServer, Struts2). Add plugin test scenarios covering the versions (Jetty 12.0.x/12.1.x; Struts 7.0.x/7.1.x/7.2.x) and update the supported list, plugin list and CHANGES. Each scenario drives the full RPC validation path in one trace - a server entry span, a client exit span, and a second entry span on a nested internal call carrying a cross-process ref - so both the entry and the context-extract sides of the plugin are proven, not just a lone entry span. The struts scenario uses a lightweight httpheader result instead of a JSP view to keep the cold first request under the plugin-test framework's 3s entry-service timeout. Add test/plugin/CLAUDE.md (plugin-test-first approach, the RPC/client validation paths, the one-version-per-minor rule, how the jvm/tomcat containers and GitHub Actions lanes pin their JDK/Tomcat base image, and the cold-start timeout gotcha) and document the supported jvm/tomcat containers in Plugin-test.md. --- .github/workflows/plugins-jdk17-test.0.yaml | 1 + .github/workflows/plugins-jdk17-test.1.yaml | 1 + .gitignore | 5 + CHANGES.md | 2 + apm-sniffer/apm-sdk-plugin/CLAUDE.md | 2 + .../jetty-server-12.x-plugin/pom.xml | 52 +++++++ .../jetty/v12/server/HandleInterceptor.java | 100 +++++++++++++ .../plugin/jetty/v12/server/SwCallback.java | 98 +++++++++++++ .../define/Jetty12ServerInstrumentation.java | 89 ++++++++++++ .../src/main/resources/skywalking-plugin.def | 18 +++ .../apm-sdk-plugin/jetty-plugin/pom.xml | 1 + apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../apm-sdk-plugin/struts2-7.x-plugin/pom.xml | 56 ++++++++ .../plugin/struts2/v7/Struts2Interceptor.java | 82 +++++++++++ .../v7/define/Struts2Instrumentation.java | 75 ++++++++++ .../src/main/resources/skywalking-plugin.def | 18 +++ .../service-agent/java-agent/Plugin-list.md | 2 + .../service-agent/java-agent/Plugin-test.md | 8 +- .../java-agent/Supported-list.md | 6 +- test/plugin/CLAUDE.md | 134 ++++++++++++++++++ .../jetty-12.x-scenario/bin/startup.sh | 21 +++ .../config/expectedData.yaml | 86 +++++++++++ .../jetty-12.x-scenario/configuration.yml | 22 +++ .../scenarios/jetty-12.x-scenario/pom.xml | 128 +++++++++++++++++ .../src/main/assembly/assembly.xml | 41 ++++++ .../testcase/jetty12xserver/Application.java | 37 +++++ .../jetty12xserver/handler/CaseHandler.java | 67 +++++++++ .../src/main/resources/log4j2.xml | 30 ++++ .../jetty-12.x-scenario/support-version.list | 18 +++ .../config/expectedData.yaml | 72 ++++++++++ .../struts2.7-scenario/configuration.yml | 21 +++ .../scenarios/struts2.7-scenario/pom.xml | 96 +++++++++++++ .../apm/testcase/struts/Case1Action.java | 28 ++++ .../apm/testcase/struts/CaseAction.java | 47 ++++++ .../testcase/struts/HealthCheckServlet.java | 41 ++++++ .../src/main/resources/log4j2.xml | 30 ++++ .../src/main/resources/struts.xml | 46 ++++++ .../src/main/webapp/WEB-INF/web.xml | 44 ++++++ .../struts2.7-scenario/support-version.list | 19 +++ 39 files changed, 1638 insertions(+), 7 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/HandleInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/SwCallback.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/define/Jetty12ServerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/struts2/v7/Struts2Interceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/struts2/v7/define/Struts2Instrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 test/plugin/CLAUDE.md create mode 100644 test/plugin/scenarios/jetty-12.x-scenario/bin/startup.sh create mode 100644 test/plugin/scenarios/jetty-12.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/jetty-12.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/jetty-12.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/jetty-12.x-scenario/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/jetty-12.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jetty12xserver/Application.java create mode 100644 test/plugin/scenarios/jetty-12.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jetty12xserver/handler/CaseHandler.java create mode 100644 test/plugin/scenarios/jetty-12.x-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/jetty-12.x-scenario/support-version.list create mode 100644 test/plugin/scenarios/struts2.7-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/struts2.7-scenario/configuration.yml create mode 100644 test/plugin/scenarios/struts2.7-scenario/pom.xml create mode 100644 test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/Case1Action.java create mode 100644 test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/CaseAction.java create mode 100644 test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/HealthCheckServlet.java create mode 100644 test/plugin/scenarios/struts2.7-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/struts2.7-scenario/src/main/resources/struts.xml create mode 100644 test/plugin/scenarios/struts2.7-scenario/src/main/webapp/WEB-INF/web.xml create mode 100644 test/plugin/scenarios/struts2.7-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk17-test.0.yaml b/.github/workflows/plugins-jdk17-test.0.yaml index 49b3675c01..b62166b155 100644 --- a/.github/workflows/plugins-jdk17-test.0.yaml +++ b/.github/workflows/plugins-jdk17-test.0.yaml @@ -79,6 +79,7 @@ jobs: - grizzly-2.3.x-4.x-workthreadpool-scenario - jetty-11.x-scenario - jetty-10.x-scenario + - jetty-12.x-scenario - spring-ai-1.x-scenario - spring-rabbitmq-scenario - graphql-20plus-scenario diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index 6be997dc0e..e4f7144dfd 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -72,6 +72,7 @@ jobs: case: - spring-6.x-scenario - spring-boot-3.x-scenario + - struts2.7-scenario - resteasy-6.x-scenario - gateway-4.x-scenario - gateway-4.1.2.x-scenario diff --git a/.gitignore b/.gitignore index da77f29d42..1efb481266 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,8 @@ packages/ /test/jacoco/*.exec test/jacoco .claude/settings.local.json + +# Generated by tools/plugin/check-javaagent-plugin-list.sh (not source) +/javaagent-position.txt +/tools/plugin/genernate-javaagent-plugin-list.txt +/tools/plugin/md-javaagent-plugin-list.txt diff --git a/CHANGES.md b/CHANGES.md index 9f994787ff..48310efdab 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,8 @@ Release Notes. * Fix `plugin.http.include_http_headers` not working on Spring Boot 3.x / Jakarta EE (apache/skywalking#13938). * Unify the Tomcat plugins into a single `tomcat` plugin (Tomcat 7 - 10) and the Jetty server plugins into a single `jetty-server` plugin (Jetty 9 - 11), each supporting both `javax.servlet` and `jakarta.servlet`. Breaking change: plugin names `tomcat-7.x/8.x` and `tomcat-10.x` are replaced by `tomcat`, and `jetty-server-9.x` and `jetty-server-11.x` by `jetty-server`; update `plugin.exclude_plugins` if you reference the old names. +* Add a Jetty 12 server plugin (`jetty-server-12.x`). Jetty 12 removed the `HttpChannel` handle target and moved request handling to the async `Server#handle(Request, Response, Callback)` core API, so it needs a separate plugin from the merged `jetty-server`. +* Add a Struts 7 plugin (`struts2-7.x`) for Jakarta Struts, whose `DefaultActionInvocation` moved to `org.apache.struts2`. * Added support for Lettuce reactive Redis commands. * Add Spring AI 1.x plugin and GenAI layer. * Fix httpclient-5.x plugin injecting sw8 propagation headers into ClickHouse HTTP requests (port 8123), causing HTTP 400. Add `PROPAGATION_EXCLUDE_PORTS` config to skip tracing (including header injection) for specified ports in the classic client interceptor. diff --git a/apm-sniffer/apm-sdk-plugin/CLAUDE.md b/apm-sniffer/apm-sdk-plugin/CLAUDE.md index b839fbe73b..81de9bc670 100644 --- a/apm-sniffer/apm-sdk-plugin/CLAUDE.md +++ b/apm-sniffer/apm-sdk-plugin/CLAUDE.md @@ -251,6 +251,8 @@ histogram.addValue(3); The plugin test framework verifies plugin functionality using Docker containers with real services and a mock OAP backend. +> See `test/plugin/CLAUDE.md` for the testing philosophy: a plugin's scenario (with one-version-per-minor coverage) is the **key** test — it proves the interceptor's cast/fetch-data logic and version compatibility by running the real framework. Do **not** over-engineer with many mock-based unit tests for a plugin. + ### Environment Requirements - MacOS/Linux - JDK 8+ diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/pom.xml new file mode 100644 index 0000000000..dfc04b5933 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/pom.xml @@ -0,0 +1,52 @@ + + + + + jetty-plugins + org.apache.skywalking + 9.7.0-SNAPSHOT + + 4.0.0 + + apm-jetty-server-12.x-plugin + jar + + jetty-server-12.x-plugin + http://maven.apache.org + + + + 12.0.36 + + + + + org.eclipse.jetty + jetty-server + ${jetty-server.version} + provided + + + diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/HandleInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/HandleInterceptor.java new file mode 100644 index 0000000000..74e08614dd --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/HandleInterceptor.java @@ -0,0 +1,100 @@ +/* + * 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.jetty.v12.server; + +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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 org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpURI; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.util.Callback; + +/** + * Enhances the core, namespace-neutral {@code org.eclipse.jetty.server.Server#handle(Request, Response, + * Callback)} — the single top-level entry invoked once per request in Jetty 12. Handling is async, so + * the entry span is prepared for async in beforeMethod, its synchronous segment ends in afterMethod, and + * it is finished (with the response status) when the wrapped {@link SwCallback} completes. + */ +public class HandleInterceptor implements InstanceMethodsAroundInterceptor { + + private static final ThreadLocal HOLDER = new ThreadLocal(); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + Request request = (Request) allArguments[0]; + Response response = (Response) allArguments[1]; + Callback callback = (Callback) allArguments[2]; + + ContextCarrier contextCarrier = new ContextCarrier(); + HttpFields headers = request.getHeaders(); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + next.setHeadValue(headers.get(next.getHeadKey())); + } + + HttpURI uri = request.getHttpURI(); + AbstractSpan span = ContextManager.createEntrySpan(uri.getPath(), contextCarrier); + Tags.URL.set(span, uri.asString()); + Tags.HTTP.METHOD.set(span, request.getMethod()); + span.setComponent(ComponentsDefine.JETTY_SERVER); + SpanLayer.asHttp(span); + span.prepareForAsync(); + + SwCallback swCallback = new SwCallback(callback, response, span); + allArguments[2] = swCallback; + HOLDER.set(swCallback); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + SwCallback swCallback = HOLDER.get(); + HOLDER.remove(); + ContextManager.stopSpan(); + // ret == true: handled; the wrapped callback fires on response completion and finishes the span. + // ret == false: not handled — Jetty writes 404 on the original callback, bypassing ours. + // ret == null: handle() threw (see handleMethodException) — Jetty writes 500. + // For the latter two the wrapped callback never fires and the status is written only after + // handle() returns, so finish here with the status Jetty's contract guarantees. + if (swCallback != null && !Boolean.TRUE.equals(ret)) { + swCallback.finishWithStatus(ret == null ? 500 : 404); + } + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan span = ContextManager.activeSpan(); + span.log(t); + span.errorOccurred(); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/SwCallback.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/SwCallback.java new file mode 100644 index 0000000000..f5193d7c05 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/SwCallback.java @@ -0,0 +1,98 @@ +/* + * 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.jetty.v12.server; + +import java.util.concurrent.atomic.AtomicBoolean; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.util.Callback; +import org.eclipse.jetty.util.thread.Invocable; + +/** + * Wraps the {@link Callback} passed to {@code Server#handle}. Jetty 12 request handling is async — the + * response status is only known when the callback completes on the (possibly different) response thread. + * On completion this reads the status, records it on the entry span and finishes the async span. It + * delegates every method to the original callback so Jetty's threading model is preserved. + */ +public class SwCallback implements Callback { + + private final Callback delegate; + private final Response response; + private final AbstractSpan span; + private final AtomicBoolean finished = new AtomicBoolean(); + + public SwCallback(Callback delegate, Response response, AbstractSpan span) { + this.delegate = delegate; + this.response = response; + this.span = span; + } + + @Override + public void succeeded() { + finishOnce(); + delegate.succeeded(); + } + + @Override + public void failed(Throwable x) { + if (finished.compareAndSet(false, true)) { + span.log(x); + span.errorOccurred(); + Tags.HTTP_RESPONSE_STATUS_CODE.set(span, response.getStatus()); + span.asyncFinish(); + } + delegate.failed(x); + } + + @Override + public Invocable.InvocationType getInvocationType() { + return delegate.getInvocationType(); + } + + /** + * Records the response status and finishes the async span exactly once. Safe to call from either the + * callback completion or the interceptor's afterMethod fallback (not-handled / exception paths). + */ + void finishOnce() { + if (finished.compareAndSet(false, true)) { + int statusCode = response.getStatus(); + Tags.HTTP_RESPONSE_STATUS_CODE.set(span, statusCode); + if (statusCode >= 400) { + span.errorOccurred(); + } + span.asyncFinish(); + } + } + + /** + * Finishes the async span exactly once with an explicit status. Used for the not-handled / exception + * fallback paths where Jetty writes the error status on the original callback after {@code handle()} + * returns — so the wrapped callback never fires and {@link Response#getStatus()} is still 0 (uncommitted). + */ + void finishWithStatus(int statusCode) { + if (finished.compareAndSet(false, true)) { + Tags.HTTP_RESPONSE_STATUS_CODE.set(span, statusCode); + if (statusCode >= 400) { + span.errorOccurred(); + } + span.asyncFinish(); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/define/Jetty12ServerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/define/Jetty12ServerInstrumentation.java new file mode 100644 index 0000000000..8b4d347af9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v12/server/define/Jetty12ServerInstrumentation.java @@ -0,0 +1,89 @@ +/* + * 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.jetty.v12.server.define; + +import java.util.Collections; +import java.util.List; +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod; +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.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * Enhances {@code org.eclipse.jetty.server.Server#handle(Request, Response, Callback)} by + * {@code HandleInterceptor}. Only Jetty 12+ declares this three-argument, {@code Callback}-terminated + * signature, so the witness method both activates the plugin exclusively on Jetty 12 and keeps it from + * overlapping the merged jetty-server plugin (which enhances the Jetty 9/10/11 {@code HttpChannel}, + * removed in Jetty 12). + */ +public class Jetty12ServerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.eclipse.jetty.server.Server"; + private static final String ENHANCE_METHOD = "handle"; + private static final String CALLBACK_CLASS = "org.eclipse.jetty.util.Callback"; + private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.jetty.v12.server.HandleInterceptor"; + + @Override + protected List witnessMethods() { + return Collections.singletonList(new WitnessMethod( + ENHANCE_CLASS, + named(ENHANCE_METHOD).and(takesArgument(2, named(CALLBACK_CLASS))) + )); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD).and(takesArguments(3)).and(takesArgument(2, named(CALLBACK_CLASS))); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..2c466d5f66 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-12.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,18 @@ +# +# 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. + +jetty-server-12.x=org.apache.skywalking.apm.plugin.jetty.v12.server.define.Jetty12ServerInstrumentation diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml index 1ac21fb14d..671cc92f91 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/pom.xml @@ -31,6 +31,7 @@ jetty-client-9.x-plugin jetty-client-9.0-plugin jetty-server-plugin + jetty-server-12.x-plugin jetty-client-11.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 829d63dd84..8bc2e1faaa 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -44,6 +44,7 @@ okhttp-common spring-plugins struts2-2.x-plugin + struts2-7.x-plugin nutz-plugins jetty-plugin spymemcached-2.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/pom.xml new file mode 100644 index 0000000000..f314ff5fba --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/pom.xml @@ -0,0 +1,56 @@ + + + + + org.apache.skywalking + apm-sdk-plugin + 9.7.0-SNAPSHOT + + 4.0.0 + + apm-struts2-7.x-plugin + jar + + struts2-7.x-plugin + + + + 7.2.1 + 6.0.0 + + + + + org.apache.struts + struts2-core + ${struts.version} + provided + + + jakarta.servlet + jakarta.servlet-api + ${jakarta-servlet-api.version} + provided + + + diff --git a/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/struts2/v7/Struts2Interceptor.java b/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/struts2/v7/Struts2Interceptor.java new file mode 100644 index 0000000000..80a42b2eaa --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/struts2/v7/Struts2Interceptor.java @@ -0,0 +1,82 @@ +/* + * 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.struts2.v7; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +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 org.apache.struts2.ServletActionContext; + +/** + * Enhances {@code org.apache.struts2.DefaultActionInvocation#invokeAction} in Struts 7.x. Struts 7 is + * Jakarta-only (Jakarta Servlet 6.0), so the servlet request/response are referenced through the + * jakarta.servlet namespace directly. + */ +public class Struts2Interceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + HttpServletRequest request = ServletActionContext.getRequest(); + ContextCarrier contextCarrier = new ContextCarrier(); + + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + next.setHeadValue(request.getHeader(next.getHeadKey())); + } + + AbstractSpan span = ContextManager.createEntrySpan(request.getRequestURI(), contextCarrier); + Tags.URL.set(span, request.getRequestURL().toString()); + Tags.HTTP.METHOD.set(span, request.getMethod()); + span.setComponent(ComponentsDefine.STRUTS2); + SpanLayer.asHttp(span); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + HttpServletResponse response = ServletActionContext.getResponse(); + + AbstractSpan span = ContextManager.activeSpan(); + int statusCode = response.getStatus(); + Tags.HTTP_RESPONSE_STATUS_CODE.set(span, statusCode); + if (statusCode >= 400) { + span.errorOccurred(); + } + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + ContextManager.activeSpan().log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/struts2/v7/define/Struts2Instrumentation.java b/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/struts2/v7/define/Struts2Instrumentation.java new file mode 100644 index 0000000000..68302e8c5a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/struts2/v7/define/Struts2Instrumentation.java @@ -0,0 +1,75 @@ +/* + * 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.struts2.v7.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 org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link Struts2Instrumentation} enhances the invokeAction method of Struts 7's + * org.apache.struts2.DefaultActionInvocation (relocated from + * com.opensymphony.xwork2.DefaultActionInvocation in Struts 2.x). The class name is + * unique to Struts 7, so it self-witnesses — no witness class is needed, and there is no overlap + * with the struts2-2.x plugin, which enhances the old XWork class. + */ +public class Struts2Instrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.apache.struts2.DefaultActionInvocation"; + private static final String ENHANCE_METHOD = "invokeAction"; + private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.struts2.v7.Struts2Interceptor"; + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..a9a45c666b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/struts2-7.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,18 @@ +# +# 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. + +struts2-7.x=org.apache.skywalking.apm.plugin.struts2.v7.define.Struts2Instrumentation 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 2e5ad78336..ac9ea19eeb 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -56,6 +56,7 @@ - jetty-client-9.0 - jetty-client-9.x - jetty-server +- jetty-server-12.x - kafka-0.11.x/1.x/2.x - kafka-3.7.x - kafka-3.9.x @@ -132,6 +133,7 @@ - spring-webflux-5.x-webclient - spymemcached-2.x - struts2-2.x +- struts2-7.x - thrift - tomcat - toolkit-counter diff --git a/docs/en/setup/service-agent/java-agent/Plugin-test.md b/docs/en/setup/service-agent/java-agent/Plugin-test.md index a40eb82e35..ca1d6ef2c2 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-test.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-test.md @@ -16,11 +16,11 @@ Every plugin maintained in the main repo requires corresponding test cases as we ## Case Base Image Introduction -The test framework provides `JVM-container` and `Tomcat-container` base images including JDK8 and JDK17. You can choose the best one for your test case. If both are suitable for your case, **`JVM-container` is preferred**. +The test framework provides `JVM-container` and `Tomcat-container` base images. You can choose the best one for your test case. If both are suitable for your case, **`JVM-container` is preferred**. ### JVM-container Image Introduction -[JVM-container](../../../../../test/plugin/containers/jvm-container) uses `eclipse-temurin:8-jdk` as the base image. `JVM-container` supports JDK8 and JDK17 as well in CI, which inherits `eclipse-temurin:8-jdk` and `eclipse-temurin:17-jdk`. +[JVM-container](../../../../../test/plugin/containers/jvm-container) uses `eclipse-temurin:8-jdk` as the default base image. In CI it is exercised on **JDK 8, 11, 17, 21 and 25** (via the `eclipse-temurin:{8,11,17,21,25}-jdk` images). It is supported to custom the base Java docker image by specify `base_image_java`. The test case project must be packaged as `project-name.zip`, including `startup.sh` and uber jar, by using `mvn clean package`. @@ -31,8 +31,8 @@ Take the following test projects as examples: ### Tomcat-container Image Introduction -[Tomcat-container](../../../../../test/plugin/containers/tomcat-container) uses `tomcat:8.5-jdk8-openjdk`, `tomcat:8.5-jdk17-openjdk` as the base image. -It is supported to custom the base Tomcat docker image by specify `base_image_tomcat`. +[Tomcat-container](../../../../../test/plugin/containers/tomcat-container) uses `tomcat:8.5-jdk8-openjdk` as the default base image. In CI it is exercised on **Tomcat 8.5, 9.0, 10.0 and 10.1** (e.g. `tomcat:8.5-jdk8-openjdk`, `tomcat:9.0.71-jdk8`, `tomcat:10.0.22-jdk8`, `tomcat:8.5-jdk17-openjdk`, `tomcat:10.1-jdk17-temurin`, `tomcat:10.1-jdk21-temurin`). Tomcat 8.5/9.0 are `javax.servlet`; Tomcat 10.0/10.1 are `jakarta.servlet`. +It is supported to custom the base Tomcat docker image by specify `base_image_tomcat`. The base image must provide `curl` (used by the container's health check); if an official image lacks it, build a small custom image that adds `curl` first — as the JDK 25 lane does with `tomcat-curl:10.1.50-jdk25-temurin`. The test case project must be packaged as `project-name.war` by using `mvn package`. Take the following test project as an example diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index ca6f481f06..1416ec3471 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -11,10 +11,10 @@ metrics based on the tracing data. * Spring MVC 3.x, 4.x 5.x with servlet 3.x * Spring MVC 6.x (Optional²) * [Nutz Web Framework](https://github.com/nutzam/nutz) 1.x - * [Struts2 MVC](http://struts.apache.org/) 2.3.x -> 2.5.x + * [Struts2 MVC](http://struts.apache.org/) 2.3.x -> 2.5.x, 7.x (Jakarta, JDK17) * Resin 3 (Optional¹), See [SkySPM Plugin Repository](https://github.com/SkyAPM/java-plugin-extensions) * Resin 4 (Optional¹), See [SkySPM Plugin Repository](https://github.com/SkyAPM/java-plugin-extensions) - * [Jetty Server](http://www.eclipse.org/jetty/) 9.x -> 11.x + * [Jetty Server](http://www.eclipse.org/jetty/) 9.x -> 12.x * [Spring WebFlux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) 5.x (Optional²) -> 6.x (Optional²) * [Undertow](http://undertow.io/) 1.3.0.Final -> 2.3.18.Final * [RESTEasy](https://resteasy.dev/) 3.1.0.Final -> 6.2.4.Final @@ -172,7 +172,7 @@ The meter plugin provides the advanced metrics collections, which are not a part * [Undertow](https://github.com/undertow-io/undertow) 2.1.x -> 2.6.x * [Tomcat](https://github.com/apache/tomcat) 7.0.x -> 10.0.x * [Dubbo](https://github.com/apache/dubbo) 2.5.x -> 2.7.x - * [Jetty](https://github.com/eclipse/jetty.project) 9.1.x -> 11.x + * [Jetty](https://github.com/eclipse/jetty.project) 9.1.x -> 12.x * [Grizzly](https://github.com/eclipse-ee4j/grizzly) 2.3.x -> 4.x * Connection Pool * Supported JDBC drviers diff --git a/test/plugin/CLAUDE.md b/test/plugin/CLAUDE.md new file mode 100644 index 0000000000..6b73f93540 --- /dev/null +++ b/test/plugin/CLAUDE.md @@ -0,0 +1,134 @@ +# CLAUDE.md - Plugin Test Guide + +This file guides AI assistants writing and changing **plugin tests** under `test/plugin/scenarios/`. +For the full test-framework mechanics (scenario layout, `configuration.yml`, `expectedData.yaml`, +containers, running locally) see the **"Plugin Test Framework"** section of +`apm-sniffer/apm-sdk-plugin/CLAUDE.md`, and `docs/.../Plugin-test.md`. + +## Testing philosophy: plugin scenarios are the key test — not unit tests + +For an agent plugin, the **plugin test scenario is the primary and sufficient test**. Do **not** +over-engineer by adding many unit tests for a plugin. + +A plugin's real risk is two things, and a scenario proves both at once by running the **real +framework**: + +1. **Cast / fetch-data logic** — the interceptor casting the intercepted arguments to the framework + types and reading request/response fields off them (headers, method, URI, status, params). Mocks + can't validate that the real framework class actually exposes those methods the way you assumed. +2. **Version compatibility** — the same interceptor must work across the supported version range. + +So: **when adding or changing a plugin, add or extend its scenario**, not a pile of mock-based unit +tests. Reserve unit tests for genuinely logic/namespace-critical **shared** code where a deterministic +in-JVM assertion earns its keep (e.g. `servlet-commons` `wrap()` resolving javax vs jakarta with both +APIs on the test classpath) — never for per-plugin interceptor mocking. + +## Validation path: assert the full span shape your plugin produces + +A scenario proves a plugin by asserting the **exact spans** the real framework makes the agent +produce. Pick the shape by what the framework actually does — and don't settle for a single entry +span when the plugin also does propagation, or you silently skip the inject/extract path. + +- **RPC / web frameworks that have both a server and a client side** (Struts, Spring MVC, gRPC, + Dubbo, HTTP servers …): drive the full round-trip — + `curl → server → its own client call → another service's endpoint`. The trace then contains + **2 entry spans + 1 exit span**: + 1. the **server entry** span for the request `curl` hit (proves the server side: extract + entry), + 2. the **client exit** span for the outbound call (proves inject + exit), + 3. a **second entry** span on the other endpoint carrying a **cross-process ref** back to the + first (proves propagation across the wire — the receiving/extract side). + + **The ref itself must be asserted** — for RPC the cross-process `refs:` block is the whole point, + so `expectedData.yaml` must include it on that second entry span with `refType: CrossProcess`, + `parentEndpoint`, `parentSpanId` (pointing at the exit span), `parentTraceSegmentId: not null`, + `parentService`, and `traceId: not null`. A scenario that asserts spans but not the ref does not + prove propagation. + + The struts2.7 scenario is exactly this: `case.action` (entry) → HttpClient (exit) → `case1.action` + (entry + ref); jetty-12 uses the same shape via a JDK-HttpURLConnection self-call. Keep that nested + self-call — it is the only thing that proves inject / extract / propagation; a lone entry span does not. + +- **Client-only plugins** (JDBC/PostgreSQL, Redis, MongoDB, an HTTP client, a message producer): the + peer is a database/broker, not another instrumented SkyWalking service, so there is **no second + entry span**. Assert just the **client exit** span (component, `peer`, and the `db.*` / `http.*` + tags). You do NOT need to stand up another service endpoint. + +## Version coverage: one version per minor (latest patch) + +`support-version.list` must cover the framework's supported range, but keep **one version per minor +version — the latest patch**, not every patch. E.g. Jetty `12.0.36` + `12.1.10`; Struts `7.0.3`, +`7.1.1`, `7.2.1`; Spring `6.0.4`, `6.1.1`, `6.2.19`. Verify each version resolves on Maven Central. +This is the compatibility proof; CI runs the scenario against each listed version. + +## How the test containers work (and where the JDK/Tomcat version really comes from) + +A scenario runs inside one of two prebuilt container images, selected by `type:` in +`configuration.yml`: + +- **`type: jvm`** → the **`agent-test-jvm`** container. Your app is a fat-jar started by + `bin/startup.sh` with `${agent_opts}` (the `-javaagent:` line — you MUST include it in + `startup.sh`). Built `FROM ${base_image_java}`. +- **`type: tomcat`** → the **`agent-test-tomcat`** container. Your app is a `*.war` dropped into + `/usr/local/tomcat/webapps/`; the agent is wired in via the container's patched `catalina.sh`. + Built `FROM ${base_image_tomcat}`. + +**The version pin is in the CI lane, not `configuration.yml`.** `configuration.yml` only says +`type: tomcat` — it does **not** choose a Tomcat version. The concrete JDK and Tomcat versions come +from the `base_image_java` / `base_image_tomcat` inputs passed to `./.github/actions/build` in the +lane's `Build` job, and **every scenario in that lane shares that one image**. So: + +- `type: tomcat` on the `plugins-jdk8-*` lane → `tomcat:8.5-jdk8` (javax); + on `plugins-jdk11-*` → `tomcat:9.0-jdk11` (javax); + on `plugins-jdk17-*` → `tomcat:10.1-jdk17` (**jakarta**). +- That is why a jakarta/Servlet-6 framework (Struts 7, Jetty 12, Spring 6) MUST be registered on a + JDK-17 lane — it needs the Tomcat-10.1 base — and a javax one on an older lane. Putting a jakarta + WAR on a Tomcat-8.5 lane just won't deploy. + +To run locally you pass the same two knobs explicitly (the defaults are the javax/JDK-8 pair): +`bash test/plugin/run.sh --base_image_java eclipse-temurin:17-jdk --base_image_tomcat tomcat:10.1-jdk17-temurin `. +Some newer bases lack `curl` (the container health check needs it) — the JDK-25 lane bakes it in +via `.github/workflows/Dockerfile-tomcat-jdk25-withCurl`. + +## How the GitHub Actions lanes work + +Scenarios are load-balanced across `.github/workflows/plugins--test..yaml` files. Each +file is one lane: its `Build` job pins `base_image_java` + `base_image_tomcat`, and its `test` job's +`matrix.case:` list names the scenarios that run on that image. Lanes exist per JDK +(`jdk8`/`jdk11`/`jdk17`/`jdk21`/`jdk25`); the trailing `.0`/`.1`/… is just a bucket to spread load. +Register a new scenario by adding its directory name to the `matrix.case:` list of the lane whose +base image matches the framework's needs — use `python3 tools/select-group.py` to pick the +least-loaded bucket in that JDK lane. + +## Cold-start and the 3s entry-service timeout (a real gotcha) + +The container's `run.sh` runs under `set -e` and hits the entry service with +`curl -s --max-time 3 ${SCENARIO_ENTRY_SERVICE}` — **no warm-up first**. So the very first (cold) +entry request must finish within **3 seconds** or `curl` exits 28 and the whole scenario fails. That +first request pays a lot of one-time cost at once: the agent's ByteBuddy enhancement of every class +it touches on that path, JIT, and — for WARs — a cold Jasper **JSP compile**, all under the +container's tight `-Xmx256m` heap and whatever CPU the runner gives, with **jacoco** simultaneously +instrumenting the `org.apache.skywalking.*` classes for coverage. + +Keep the entry path's cold cost low: + +- Don't render a **JSP** from the entry action if a lightweight result works (e.g. Struts + `httpheader`, a plain-text/stream result). The view is irrelevant to what a plugin scenario + verifies (entry/exit spans, tags, propagation), and a cold Jasper compile is expensive. +- Be extra careful when the entry action makes a **nested internal call** (for cross-process + propagation coverage): if that nested request also does cold work (a JSP compile) *while* the + outer request is still cold-enhancing Struts/HttpClient, the two cold-start storms contend for the + limited CPU and heap and blow up **super-linearly** (observed ~0.5s each in isolation but ~3–20s + nested under throttle). This is a slow first request, not a plugin bug — verify with a + CPU-throttled container (`docker run --cpus=0.5 …`) before assuming a hang. + +## Practical notes + +- One scenario per plugin (or per javax/jakarta era). Mirror an existing sibling scenario as a + template and change only what differs (framework version, namespace, deployment model). +- Match `type:` to the deployment: `jvm` (fat-jar started by `bin/startup.sh`, `${agent_opts}` + required) or `tomcat` (WAR on a container). Jakarta/newer frameworks go in a JDK-17 CI group. +- Assert the entry span shape that exercises the plugin's data logic: `componentId`, `spanType: Entry`, + `spanLayer: Http`, and the `url` / `http.method` / `http.status_code` (and `http.params` / + `http.headers` where the plugin collects them) tags, plus cross-process refs. +- Register the scenario in the right `.github/workflows/plugins-*.yaml` matrix (use + `python3 tools/select-group.py` to pick the least-loaded group for its JDK lane). diff --git a/test/plugin/scenarios/jetty-12.x-scenario/bin/startup.sh b/test/plugin/scenarios/jetty-12.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..ea5bec3c39 --- /dev/null +++ b/test/plugin/scenarios/jetty-12.x-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/jetty-12.x-scenario.jar & diff --git a/test/plugin/scenarios/jetty-12.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/jetty-12.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..b3e44c9df3 --- /dev/null +++ b/test/plugin/scenarios/jetty-12.x-scenario/config/expectedData.yaml @@ -0,0 +1,86 @@ +# 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: jetty-12.x-scenario + segmentSize: gt 2 + segments: + - segmentId: not null + spans: + - operationName: /jetty-12.x-scenario/case/case1 + parentSpanId: '-1' + spanId: '0' + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: '19' + isError: 'false' + spanType: Entry + peer: '' + skipAnalysis: 'false' + tags: + - key: url + value: http://localhost:18080/jetty-12.x-scenario/case/case1 + - key: http.method + value: GET + - key: http.status_code + value: '200' + refs: + - parentEndpoint: /jetty-12.x-scenario/case/jetty-12.x-scenario + networkAddress: localhost:18080 + refType: CrossProcess + parentSpanId: '1' + parentTraceSegmentId: not null + parentServiceInstance: not null + parentService: jetty-12.x-scenario + traceId: not null + - segmentId: not null + spans: + - operationName: /jetty-12.x-scenario/case/case1 + parentSpanId: '0' + spanId: '1' + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: '2' + isError: 'false' + spanType: Exit + peer: localhost:18080 + skipAnalysis: 'false' + tags: + - key: url + value: http://localhost:18080/jetty-12.x-scenario/case/case1 + - key: http.method + value: GET + - key: http.status_code + value: '200' + - operationName: /jetty-12.x-scenario/case/jetty-12.x-scenario + parentSpanId: '-1' + spanId: '0' + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: '19' + isError: 'false' + spanType: Entry + peer: '' + skipAnalysis: 'false' + tags: + - key: url + value: http://localhost:18080/jetty-12.x-scenario/case/jetty-12.x-scenario + - key: http.method + value: GET + - key: http.status_code + value: '200' diff --git a/test/plugin/scenarios/jetty-12.x-scenario/configuration.yml b/test/plugin/scenarios/jetty-12.x-scenario/configuration.yml new file mode 100644 index 0000000000..2db90d0c99 --- /dev/null +++ b/test/plugin/scenarios/jetty-12.x-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:18080/jetty-12.x-scenario/case/jetty-12.x-scenario +healthCheck: http://localhost:18080/jetty-12.x-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: +dependencies: diff --git a/test/plugin/scenarios/jetty-12.x-scenario/pom.xml b/test/plugin/scenarios/jetty-12.x-scenario/pom.xml new file mode 100644 index 0000000000..6a28e254bf --- /dev/null +++ b/test/plugin/scenarios/jetty-12.x-scenario/pom.xml @@ -0,0 +1,128 @@ + + + + + org.apache.skywalking.apm.testcase + jetty-12.x-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 17 + 3.8.1 + + 12.0.36 + + 2.6.2 + + + skywalking-jetty-12.x-scenario + + + + org.eclipse.jetty + jetty-server + ${test.framework.version} + + + + org.apache.httpcomponents + httpclient + 4.3 + + + + + + jetty-12.x-scenario + + + org.apache.maven.plugins + maven-shade-plugin + 3.1.0 + + + package + + shade + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + org.apache.skywalking.apm.testcase.jetty12xserver.Application + + + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + diff --git a/test/plugin/scenarios/jetty-12.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/jetty-12.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..4be83c4cb7 --- /dev/null +++ b/test/plugin/scenarios/jetty-12.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/jetty-12.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/jetty-12.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jetty12xserver/Application.java b/test/plugin/scenarios/jetty-12.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jetty12xserver/Application.java new file mode 100644 index 0000000000..aecb666125 --- /dev/null +++ b/test/plugin/scenarios/jetty-12.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jetty12xserver/Application.java @@ -0,0 +1,37 @@ +/* + * 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.testcase.jetty12xserver; + +import org.apache.skywalking.apm.testcase.jetty12xserver.handler.CaseHandler; +import org.eclipse.jetty.server.Server; + +/** + * Embedded Jetty 12 server. Jetty 12 handling routes every request through + * {@code org.eclipse.jetty.server.Server#handle(Request, Response, Callback)} — the method the + * jetty-server-12.x plugin enhances — before delegating to the top-level {@link CaseHandler}. + */ +public class Application { + + public static void main(String[] args) throws Exception { + Server server = new Server(18080); + server.setHandler(new CaseHandler()); + server.start(); + server.join(); + } +} diff --git a/test/plugin/scenarios/jetty-12.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jetty12xserver/handler/CaseHandler.java b/test/plugin/scenarios/jetty-12.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jetty12xserver/handler/CaseHandler.java new file mode 100644 index 0000000000..201ab06792 --- /dev/null +++ b/test/plugin/scenarios/jetty-12.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jetty12xserver/handler/CaseHandler.java @@ -0,0 +1,67 @@ +/* + * 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.testcase.jetty12xserver.handler; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import org.apache.http.HttpEntity; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.util.Callback; + +/** + * Top-level Jetty 12 core handler. + * + * The entry service {@code /jetty-12.x-scenario/case/jetty-12.x-scenario} makes a nested internal + * call to {@code /jetty-12.x-scenario/case/case1} on the same server. This exercises both sides of + * the jetty-server-12.x plugin in one trace: the entry span for the inbound request, the HttpClient + * exit span for the outbound call (inject), and a second entry span on {@code case1} that extracts + * the propagated context into a cross-process ref (the receiving/extract side). The health check + * {@code /case/healthCheck} and the nested {@code /case/case1} endpoint simply return 200. + */ +public class CaseHandler extends Handler.Abstract { + + @Override + public boolean handle(Request request, Response response, Callback callback) throws Exception { + String path = request.getHttpURI().getPath(); + if (path != null && path.endsWith("/case/jetty-12.x-scenario")) { + visit("http://localhost:18080/jetty-12.x-scenario/case/case1"); + } + response.setStatus(200); + response.write(true, ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8)), callback); + return true; + } + + private static void visit(String url) throws Exception { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpGet httpget = new HttpGet(url); + ResponseHandler responseHandler = response -> { + HttpEntity entity = response.getEntity(); + return entity != null ? EntityUtils.toString(entity) : null; + }; + httpClient.execute(httpget, responseHandler); + } + } +} diff --git a/test/plugin/scenarios/jetty-12.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/jetty-12.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..b5cda5ae8a --- /dev/null +++ b/test/plugin/scenarios/jetty-12.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/test/plugin/scenarios/jetty-12.x-scenario/support-version.list b/test/plugin/scenarios/jetty-12.x-scenario/support-version.list new file mode 100644 index 0000000000..6c62f269a7 --- /dev/null +++ b/test/plugin/scenarios/jetty-12.x-scenario/support-version.list @@ -0,0 +1,18 @@ +# 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. + +12.0.36 +12.1.10 diff --git a/test/plugin/scenarios/struts2.7-scenario/config/expectedData.yaml b/test/plugin/scenarios/struts2.7-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..02d7206ab2 --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/config/expectedData.yaml @@ -0,0 +1,72 @@ +# 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: struts2.7-scenario + segmentSize: gt 2 + segments: + - segmentId: not null + spans: + - operationName: /struts2.7-scenario/case/case1.action + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 15 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/struts2.7-scenario/case/case1.action'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: /struts2.7-scenario/case/case.action, networkAddress: 'localhost:8080', + refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: struts2.7-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: /struts2.7-scenario/case/case1.action + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 2 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/struts2.7-scenario/case/case1.action'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /struts2.7-scenario/case/case.action + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 15 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/struts2.7-scenario/case/case.action'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/struts2.7-scenario/configuration.yml b/test/plugin/scenarios/struts2.7-scenario/configuration.yml new file mode 100644 index 0000000000..b16e56768e --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/configuration.yml @@ -0,0 +1,21 @@ +# 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: tomcat +entryService: http://localhost:8080/struts2.7-scenario/case/case.action +healthCheck: http://localhost:8080/struts2.7-scenario/healthCheck +environment: +dependencies: diff --git a/test/plugin/scenarios/struts2.7-scenario/pom.xml b/test/plugin/scenarios/struts2.7-scenario/pom.xml new file mode 100644 index 0000000000..beede09526 --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/pom.xml @@ -0,0 +1,96 @@ + + + + + org.apache.skywalking.apm.testcase + struts2.7-scenario + 1.0.0 + war + + 4.0.0 + + skywalking-struts2.7-scenario + + + UTF-8 + + 17 + 3.8.1 + 7.2.1 + 6.0.0 + 1.18.42 + + + + + jakarta.servlet + jakarta.servlet-api + ${jakarta-servlet-api.version} + provided + + + org.apache.logging.log4j + log4j-api + 2.8.1 + + + org.apache.logging.log4j + log4j-core + 2.8.1 + + + org.projectlombok + lombok + ${lombok.version} + provided + + + org.apache.struts + struts2-core + ${test.framework.version} + + + org.apache.httpcomponents + httpclient + 4.3 + + + + + struts2.7-scenario + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-war-plugin + 3.3.1 + + + + diff --git a/test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/Case1Action.java b/test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/Case1Action.java new file mode 100644 index 0000000000..9f40d9c99f --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/Case1Action.java @@ -0,0 +1,28 @@ +/* + * 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.testcase.struts; + +import java.io.IOException; + +public class Case1Action { + + public String execute() throws IOException { + return "SUCCESS"; + } +} diff --git a/test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/CaseAction.java b/test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/CaseAction.java new file mode 100644 index 0000000000..89a4c70e36 --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/CaseAction.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.testcase.struts; + +import org.apache.http.HttpEntity; +import org.apache.http.client.ResponseHandler; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; + +public class CaseAction { + + public String execute() throws IOException { + visit(); + return "SUCCESS"; + } + + private static void visit() throws IOException { + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + HttpGet httpget = new HttpGet("http://localhost:8080/struts2.7-scenario/case/case1.action"); + ResponseHandler responseHandler = response -> { + HttpEntity entity = response.getEntity(); + return entity != null ? EntityUtils.toString(entity) : null; + }; + httpClient.execute(httpget, responseHandler); + } + } +} diff --git a/test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/HealthCheckServlet.java b/test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/HealthCheckServlet.java new file mode 100644 index 0000000000..31458cea43 --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/src/main/java/org/apache/skywalking/apm/testcase/struts/HealthCheckServlet.java @@ -0,0 +1,41 @@ +/* + * 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.testcase.struts; + +import java.io.IOException; +import java.io.PrintWriter; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +public class HealthCheckServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + // your codes + PrintWriter writer = resp.getWriter(); + writer.write("Success"); + writer.flush(); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + doGet(req, resp); + } +} diff --git a/test/plugin/scenarios/struts2.7-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/struts2.7-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..b5cda5ae8a --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/test/plugin/scenarios/struts2.7-scenario/src/main/resources/struts.xml b/test/plugin/scenarios/struts2.7-scenario/src/main/resources/struts.xml new file mode 100644 index 0000000000..62faf006d4 --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/src/main/resources/struts.xml @@ -0,0 +1,46 @@ + + + + + + + + + + 200 + + + + + 200 + + + + diff --git a/test/plugin/scenarios/struts2.7-scenario/src/main/webapp/WEB-INF/web.xml b/test/plugin/scenarios/struts2.7-scenario/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..a43b33cc55 --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,44 @@ + + + skywalking-struts2.7-scenario + + + struts2 + org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter + + + + struts2 + /case/* + + + + healthCheck + org.apache.skywalking.apm.testcase.struts.HealthCheckServlet + + + + healthCheck + /healthCheck + + diff --git a/test/plugin/scenarios/struts2.7-scenario/support-version.list b/test/plugin/scenarios/struts2.7-scenario/support-version.list new file mode 100644 index 0000000000..5fcb5f103f --- /dev/null +++ b/test/plugin/scenarios/struts2.7-scenario/support-version.list @@ -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. + +7.0.3 +7.1.1 +7.2.1 From 67c9afa00cde91fb5fae6cc5a7d34d88e2579b7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Tue, 7 Jul 2026 15:13:21 +0800 Subject: [PATCH 114/114] Add mixed-classpath scenario and Tomcat http.headers collection (#814) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two related follow-ups to the #812 servlet-commons unification, both about HTTP request-tag collection on the Tomcat/servlet path. 1. spring-6.x-mixed-servlet-scenario — an end-to-end repro of the #13938 field condition: a Jakarta Spring 6 WAR that ALSO carries javax.servlet-api:4.0.1 at compile scope, so both javax.servlet.* (from WEB-INF/lib) and jakarta.servlet.* (from the Tomcat 10.1 container) are loadable in the deployed webapp at once. The scenario asserts http.headers and http.params are still collected on the jakarta entry span, proving servlet-commons' runtime instanceof dispatch resolves the live request under a mixed classpath — previously only covered by the HttpRequestWrappersTest unit test. One version by design (the resolution is version-independent; version compatibility is already covered by spring-6.x-scenario). 2. Tomcat http.headers — http.headers was emitted only by the Spring MVC plugin, so plugin.http.include_http_headers was a no-op for plain servlet apps served by the Tomcat plugin. Add INCLUDE_HTTP_HEADERS + HTTP_HEADERS_LENGTH_THRESHOLD to TomcatPluginConfig.Plugin.Http — the shared plugin.http.* namespace already used by the Spring MVC and HttpClient plugins, so no new config key and no agent.config change — and collect the configured request headers in TomcatInvokeInterceptor, guarded no-op when the config is empty. Proven on the dedicated Tomcat scenarios, where the Tomcat plugin owns the entry span: tomcat-9x (javax, Tomcat 9) and tomcat-10x (jakarta, Tomcat 10) now carry a mock_header header and a q1 query param on their internal self-call and assert http.headers + http.params, which also fills the previously-missing jakarta http.params coverage. --- .github/workflows/plugins-jdk17-test.1.yaml | 1 + CHANGES.md | 1 + .../tomcat/TomcatInvokeInterceptor.java | 28 ++ .../apm/plugin/tomcat/TomcatPluginConfig.java | 14 + .../config/expectedData.yaml | 379 ++++++++++++++++++ .../configuration.yml | 23 ++ .../spring-6.x-mixed-servlet-scenario/pom.xml | 143 +++++++ .../skywalking/apm/testcase/entity/User.java | 53 +++ .../implinterface/TestCaseController.java | 35 ++ .../implinterface/TestCaseInterface.java | 31 ++ .../apm/testcase/inherit/ChildController.java | 28 ++ .../testcase/inherit/ParentController.java | 32 ++ .../testcase/restapi/RestCaseController.java | 77 ++++ .../resttemplate/RestTemplateController.java | 85 ++++ .../apm/testcase/spring3/CaseController.java | 41 ++ .../spring3/component/TestComponentBean.java | 29 ++ .../spring3/dao/TestRepositoryBean.java | 29 ++ .../spring3/service/TestServiceBean.java | 38 ++ .../src/main/resources/log4j2.xml | 30 ++ .../webapp/WEB-INF/spring-mvc-servlet.xml | 30 ++ .../src/main/webapp/WEB-INF/web.xml | 35 ++ .../support-version.list | 21 + .../config/expectedData.yaml | 4 +- .../tomcat-10x-scenario/configuration.yml | 2 + .../apm/testcase/tomcat10x/CaseServlet.java | 5 +- .../config/expectedData.yaml | 4 +- .../tomcat-9x-scenario/configuration.yml | 2 + .../apm/testcase/tomcat9x/CaseServlet.java | 5 +- 28 files changed, 1201 insertions(+), 4 deletions(-) create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/configuration.yml create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/pom.xml create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/resources/log4j2.xml create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/webapp/WEB-INF/web.xml create mode 100644 test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/support-version.list diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index e4f7144dfd..7738b85f44 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -71,6 +71,7 @@ jobs: matrix: case: - spring-6.x-scenario + - spring-6.x-mixed-servlet-scenario - spring-boot-3.x-scenario - struts2.7-scenario - resteasy-6.x-scenario diff --git a/CHANGES.md b/CHANGES.md index 48310efdab..4daf294f74 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ Release Notes. ------------------ * Fix `plugin.http.include_http_headers` not working on Spring Boot 3.x / Jakarta EE (apache/skywalking#13938). +* Support `plugin.http.include_http_headers` in the Tomcat plugin, collecting the configured request headers as the `http.headers` tag on Tomcat entry spans (e.g. RESTEasy on Tomcat), consistent with the Spring MVC plugin. Honors the shared `plugin.http.http_headers_length_threshold`. * Unify the Tomcat plugins into a single `tomcat` plugin (Tomcat 7 - 10) and the Jetty server plugins into a single `jetty-server` plugin (Jetty 9 - 11), each supporting both `javax.servlet` and `jakarta.servlet`. Breaking change: plugin names `tomcat-7.x/8.x` and `tomcat-10.x` are replaced by `tomcat`, and `jetty-server-9.x` and `jetty-server-11.x` by `jetty-server`; update `plugin.exclude_plugins` if you reference the old names. * Add a Jetty 12 server plugin (`jetty-server-12.x`). Jetty 12 removed the `HttpChannel` handle target and moved request handling to the async `Server#handle(Request, Response, Callback)` core API, so it needs a separate plugin from the merged `jetty-server`. * Add a Struts 7 plugin (`struts2-7.x`) for Jakarta Struts, whose `DefaultActionInvocation` moved to `org.apache.struts2`. diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptor.java index 9cb009199a..8208a2a4c6 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatInvokeInterceptor.java @@ -37,8 +37,11 @@ import org.apache.tomcat.util.http.Parameters; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor { @@ -64,6 +67,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr if (TomcatPluginConfig.Plugin.Tomcat.COLLECT_HTTP_PARAMS) { collectHttpParam(request, span); } + + if (!CollectionUtil.isEmpty(TomcatPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS)) { + collectHttpHeaders(request, span); + } } @Override @@ -115,4 +122,25 @@ private void collectHttpParam(Request request, AbstractSpan span) { Tags.HTTP.PARAMS.set(span, tagValue); } } + + private void collectHttpHeaders(Request request, AbstractSpan span) { + final List headersList = new ArrayList<>(TomcatPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size()); + TomcatPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream() + .filter(headerName -> request.getHeaders(headerName) != null) + .forEach(headerName -> { + Enumeration headerValues = request.getHeaders(headerName); + List valueList = Collections.list(headerValues); + if (!CollectionUtil.isEmpty(valueList)) { + headersList.add(headerName + "=" + valueList); + } + }); + + if (!headersList.isEmpty()) { + String tagValue = String.join("\n", headersList); + tagValue = TomcatPluginConfig.Plugin.Http.HTTP_HEADERS_LENGTH_THRESHOLD > 0 ? + StringUtil.cut(tagValue, TomcatPluginConfig.Plugin.Http.HTTP_HEADERS_LENGTH_THRESHOLD) : + tagValue; + Tags.HTTP.HEADERS.set(span, tagValue); + } + } } diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatPluginConfig.java b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatPluginConfig.java index 0a1d713cf9..8a99337863 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatPluginConfig.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat/TomcatPluginConfig.java @@ -18,6 +18,7 @@ package org.apache.skywalking.apm.plugin.tomcat; +import java.util.List; import org.apache.skywalking.apm.agent.core.boot.PluginConfig; public class TomcatPluginConfig { @@ -38,6 +39,19 @@ public static class Http { * for the sake of performance */ public static int HTTP_PARAMS_LENGTH_THRESHOLD = 1024; + + /** + * When {@link Http#INCLUDE_HTTP_HEADERS} declares header names, this threshold controls the length + * limitation of all header values. use negative values to keep and send the complete headers. + * Note. this config item is added for the sake of performance. + */ + public static int HTTP_HEADERS_LENGTH_THRESHOLD = 2048; + + /** + * It controls what header data should be collected, this is for security purpose, values must be in lower + * case. Shares the {@code plugin.http.include_http_headers} config key with the other HTTP server plugins. + */ + public static List INCLUDE_HTTP_HEADERS; } } } diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/config/expectedData.yaml b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..992a34dafd --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/config/expectedData.yaml @@ -0,0 +1,379 @@ +# 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: spring-6.x-mixed-servlet-scenario + segmentSize: ge 10 + segments: + - segmentId: not null + spans: + - operationName: HEAD:/healthCheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/healthCheck'} + - {key: http.method, value: HEAD} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: test.apache.skywalking.apm.testcase.spring3.component.TestComponentBean.componentMethod + parentSpanId: 1 + spanId: 2 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 93 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: test.apache.skywalking.apm.testcase.spring3.dao.TestRepositoryBean.doSomeStuff + parentSpanId: 1 + spanId: 3 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 93 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: test.apache.skywalking.apm.testcase.spring3.service.TestServiceBean.doSomeBusiness + parentSpanId: 0 + spanId: 1 + spanLayer: Unknown + startTime: nq 0 + endTime: nq 0 + componentId: 93 + isError: false + spanType: Local + peer: '' + skipAnalysis: 'false' + - operationName: GET:/case/spring3 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/case/spring3'} + - {key: http.method, value: GET} + - {key: http.headers, value: 'mock_header=[mock_value]'} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 1, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-6.x-mixed-servlet-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'POST:/create/' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/create/'} + - {key: http.method, value: POST} + - {key: http.status_code, value: '201'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 2, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-6.x-mixed-servlet-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'GET:/get/{id}' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/get/1'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 3, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-6.x-mixed-servlet-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'PUT:/update/{id}' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/update/1'} + - {key: http.method, value: PUT} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 4, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-6.x-mixed-servlet-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'DELETE:/delete/{id}' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/delete/1'} + - {key: http.method, value: DELETE} + - {key: http.status_code, value: '204'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 5, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-6.x-mixed-servlet-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GET:/inherit/child/test + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/inherit/child/test'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 6, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-6.x-mixed-servlet-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: GET:/impl/requestmapping + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/impl/requestmapping'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 7, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-6.x-mixed-servlet-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: 'GET:/impl/restmapping' + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/impl/restmapping'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + refs: + - {parentEndpoint: GET:/case/resttemplate, networkAddress: 'localhost:8080', refType: CrossProcess, + parentSpanId: 8, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: spring-6.x-mixed-servlet-scenario, traceId: not null} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: /spring-6.x-mixed-servlet-scenario/case/spring3 + parentSpanId: 0 + spanId: 1 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/case/spring3'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-6.x-mixed-servlet-scenario/create/ + parentSpanId: 0 + spanId: 2 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/create/'} + - {key: http.method, value: POST} + - {key: http.status_code, value: '201'} + skipAnalysis: 'false' + - operationName: /spring-6.x-mixed-servlet-scenario/get/1 + parentSpanId: 0 + spanId: 3 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/get/1'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-6.x-mixed-servlet-scenario/update/1 + parentSpanId: 0 + spanId: 4 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/update/1'} + - {key: http.method, value: PUT} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-6.x-mixed-servlet-scenario/delete/1 + parentSpanId: 0 + spanId: 5 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 13 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/delete/1'} + - {key: http.method, value: DELETE} + - {key: http.status_code, value: '204'} + skipAnalysis: 'false' + - operationName: /spring-6.x-mixed-servlet-scenario/inherit/child/test + parentSpanId: 0 + spanId: 6 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/inherit/child/test'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-6.x-mixed-servlet-scenario/impl/requestmapping + parentSpanId: 0 + spanId: 7 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/impl/requestmapping'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: /spring-6.x-mixed-servlet-scenario/impl/restmapping + parentSpanId: 0 + spanId: 8 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 12 + isError: false + spanType: Exit + peer: localhost:8080 + tags: + - {key: http.method, value: GET} + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/impl/restmapping'} + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' + - operationName: GET:/case/resttemplate + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 14 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/spring-6.x-mixed-servlet-scenario/case/resttemplate'} + - {key: http.method, value: GET} + - key: http.params + value: |- + q1=[v1] + chinese=[中文] + - {key: http.status_code, value: '200'} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/configuration.yml b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/configuration.yml new file mode 100644 index 0000000000..8ca8d8b42b --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/configuration.yml @@ -0,0 +1,23 @@ +# 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: tomcat +entryService: '"http://localhost:8080/spring-6.x-mixed-servlet-scenario/case/resttemplate?q1=v1&chinese=%e4%b8%ad%e6%96%87"' +healthCheck: http://localhost:8080/spring-6.x-mixed-servlet-scenario/healthCheck +runningMode: with_optional +withPlugins: apm-spring-annotation-plugin-*.jar;apm-*-6.x-plugin-*.jar +environment: + - CATALINA_OPTS="-Dskywalking.plugin.http.include_http_headers=mock_header -Dskywalking.plugin.springmvc.collect_http_params=true" diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/pom.xml b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/pom.xml new file mode 100644 index 0000000000..4cd3b19779 --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/pom.xml @@ -0,0 +1,143 @@ + + + + 4.0.0 + + org.apache.skywalking + spring-6.x-mixed-servlet-scenario + 5.0.0 + + war + + + UTF-8 + 17 + 3.11.0 + 6.0.0 + spring + + + skywalking-spring-6.x-mixed-servlet-scenario + + + + org.springframework + spring-context + ${test.framework.version} + + + org.springframework + spring-aop + ${test.framework.version} + + + org.springframework + spring-webmvc + ${test.framework.version} + + + org.springframework + spring-web + ${test.framework.version} + + + + com.fasterxml.jackson.core + jackson-databind + 2.14.3 + + + + com.google.code.gson + gson + 2.9.1 + + + + com.squareup.okhttp3 + okhttp + 4.10.0 + + + + org.apache.logging.log4j + log4j-api + 2.19.0 + + + org.apache.logging.log4j + log4j-core + 2.19.0 + + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + + + + javax.servlet + javax.servlet-api + 4.0.1 + + + + + spring-6.x-mixed-servlet-scenario + + + org.apache.maven.plugins + maven-war-plugin + 3.3.1 + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + true + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + + + + + spring-snapshots + https://repo.spring.io/snapshot + + + spring-milestones + https://repo.spring.io/milestone + + + \ No newline at end of file diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.java new file mode 100644 index 0000000000..e7fb1871e5 --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/entity/User.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 test.apache.skywalking.apm.testcase.entity; + +public class User { + + private int id; + private String userName; + + public User(int id) { + this.id = id; + } + + public User(int id, String userName) { + this.id = id; + this.userName = userName; + } + + public User() { + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java new file mode 100644 index 0000000000..7a95a9318a --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseController.java @@ -0,0 +1,35 @@ +/* + * 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.implinterface; + +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestCaseController implements TestCaseInterface { + + @Override + public String implRequestMappingAnnotationTestCase() { + return "implRequestMappingAnnotationTestCase"; + } + + @Override + public String implRestAnnotationTestCase() { + return "implRestAnnotationTestCase"; + } +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java new file mode 100644 index 0000000000..4fea97b7b1 --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/implinterface/TestCaseInterface.java @@ -0,0 +1,31 @@ +/* + * 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.implinterface; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@RequestMapping("/impl") +public interface TestCaseInterface { + @RequestMapping(path = "/requestmapping") + String implRequestMappingAnnotationTestCase(); + + @GetMapping("/restmapping") + String implRestAnnotationTestCase(); +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java new file mode 100644 index 0000000000..27ddf54c76 --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ChildController.java @@ -0,0 +1,28 @@ +/* + * 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.inherit; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/inherit/child") +public class ChildController extends ParentController { + +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java new file mode 100644 index 0000000000..16b928100d --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/inherit/ParentController.java @@ -0,0 +1,32 @@ +/* + * 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.inherit; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/inherit/parent") +public class ParentController { + + @RequestMapping("test") + public String test(Integer param) { + return "parent-a" + param; + } +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java new file mode 100644 index 0000000000..6792ecb712 --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/restapi/RestCaseController.java @@ -0,0 +1,77 @@ +/* + * 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.restapi; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.util.UriComponentsBuilder; +import test.apache.skywalking.apm.testcase.entity.User; + +@RestController +public class RestCaseController { + + private static final Map USERS = new ConcurrentHashMap(); + + @GetMapping(value = "/get/{id}") + @ResponseBody + private ResponseEntity getUser(@PathVariable("id") int id) throws InterruptedException { + User currentUser = new User(id, "a"); + return ResponseEntity.ok(currentUser); + } + + @PostMapping(value = "/create/") + @ResponseBody + public ResponseEntity createUser(@RequestBody User user, + UriComponentsBuilder ucBuilder) throws InterruptedException { + USERS.put(user.getId(), user); + HttpHeaders headers = new HttpHeaders(); + headers.setLocation(ucBuilder.path("/get/{id}").buildAndExpand(user.getId()).toUri()); + return new ResponseEntity(headers, HttpStatus.CREATED); + } + + @PutMapping(value = "/update/{id}") + @ResponseBody + public ResponseEntity updateUser(@PathVariable("id") int id, + @RequestBody User user) throws InterruptedException { + User currentUser = new User(id, user.getUserName()); + return ResponseEntity.ok(currentUser); + } + + @DeleteMapping(value = "/delete/{id}") + @ResponseBody + public ResponseEntity deleteUser(@PathVariable("id") int id) throws InterruptedException { + User currentUser = USERS.get(id); + if (currentUser == null) { + return ResponseEntity.noContent().build(); + } + USERS.remove(id); + return ResponseEntity.noContent().build(); + } +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java new file mode 100644 index 0000000000..62b93ac01a --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/resttemplate/RestTemplateController.java @@ -0,0 +1,85 @@ +/* + * 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.resttemplate; + +import java.io.IOException; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.http.HttpEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestTemplate; +import test.apache.skywalking.apm.testcase.entity.User; + +@RestController +public class RestTemplateController { + + private static final String SUCCESS = "Success"; + + private static final Logger LOGGER = LogManager.getLogger(RestTemplateController.class); + + private static final String URL = "http://localhost:8080/spring-6.x-mixed-servlet-scenario"; + + @RequestMapping("/case/resttemplate") + @ResponseBody + public String restTemplate() throws IOException { + Request request = new Request.Builder().header("mock_header", "mock_value").url(URL + "/case/spring3").build(); + Response response = new OkHttpClient().newCall(request).execute(); + LOGGER.info(response.toString()); + + // Create user + HttpEntity userEntity = new HttpEntity<>(new User(1, "a")); + new RestTemplate().postForEntity(URL + "/create/", userEntity, Void.class); + + // Find User + new RestTemplate().getForEntity(URL + "/get/{id}", User.class, 1); + + //Modify user + HttpEntity updateUserEntity = new HttpEntity<>(new User(1, "b")); + new RestTemplate().put(URL + "/update/{id}", updateUserEntity, userEntity.getBody().getId(), 1); + + //Delete user + new RestTemplate().delete(URL + "/delete/{id}", 1); + + Request inheritRequest = new Request.Builder().url(URL + "/inherit/child/test").build(); + response = new OkHttpClient().newCall(inheritRequest).execute(); + LOGGER.info(response.toString()); + + Request implRequestMappingRequest = new Request.Builder().url(URL + "/impl/requestmapping").build(); + response = new OkHttpClient().newCall(implRequestMappingRequest).execute(); + LOGGER.info(response.toString()); + + Request implRestMappingRequest = new Request.Builder().url(URL + "/impl/restmapping").build(); + response = new OkHttpClient().newCall(implRestMappingRequest).execute(); + LOGGER.info(response.toString()); + + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java new file mode 100644 index 0000000000..501c691579 --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/CaseController.java @@ -0,0 +1,41 @@ +/* + * 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.spring3; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import test.apache.skywalking.apm.testcase.spring3.service.TestServiceBean; + +@Controller +public class CaseController { + + private static final String SUCCESS = "Success"; + + @Autowired + private TestServiceBean testServiceBean; + + @RequestMapping(value = "/case/spring3") + @ResponseBody + public String updateUser() { + testServiceBean.doSomeBusiness("test"); + return SUCCESS; + } +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java new file mode 100644 index 0000000000..274aaf490e --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/component/TestComponentBean.java @@ -0,0 +1,29 @@ +/* + * 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.spring3.component; + +import org.springframework.stereotype.Component; + +@Component +public class TestComponentBean { + + public String componentMethod(String name) { + return name + "-" + "dealWith-component"; + } +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java new file mode 100644 index 0000000000..84f871ef55 --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/dao/TestRepositoryBean.java @@ -0,0 +1,29 @@ +/* + * 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.spring3.dao; + +import org.springframework.stereotype.Repository; + +@Repository +public class TestRepositoryBean { + + public String doSomeStuff(String name) { + return name + "-dealWithRepository"; + } +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java new file mode 100644 index 0000000000..811fe11648 --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/java/test/apache/skywalking/apm/testcase/spring3/service/TestServiceBean.java @@ -0,0 +1,38 @@ +/* + * 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.spring3.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import test.apache.skywalking.apm.testcase.spring3.dao.TestRepositoryBean; +import test.apache.skywalking.apm.testcase.spring3.component.TestComponentBean; + +@Service +public class TestServiceBean { + @Autowired + private TestComponentBean componentBean; + + @Autowired + private TestRepositoryBean repositoryBean; + + public void doSomeBusiness(String name) { + componentBean.componentMethod(name); + repositoryBean.doSomeStuff(name); + } +} diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..b5cda5ae8a --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml new file mode 100644 index 0000000000..b8a2885d3e --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/webapp/WEB-INF/spring-mvc-servlet.xml @@ -0,0 +1,30 @@ + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/webapp/WEB-INF/web.xml b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..e64a37771f --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,35 @@ + + + + skywalking-spring-6.x-mixed-servlet-scenario + + + spring-mvc + org.springframework.web.servlet.DispatcherServlet + 1 + + + spring-mvc + / + + diff --git a/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/support-version.list b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/support-version.list new file mode 100644 index 0000000000..845ea5eb10 --- /dev/null +++ b/test/plugin/scenarios/spring-6.x-mixed-servlet-scenario/support-version.list @@ -0,0 +1,21 @@ +# 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. + +# Single version by design: this scenario tests the mixed javax+jakarta CLASSPATH +# condition (issue #13938), which is resolved by servlet-commons' runtime instanceof +# dispatch and is independent of the Spring version. Version compatibility across +# 6.0/6.1/6.2 is already covered by spring-6.x-scenario. Do NOT expand this list. +6.2.19 diff --git a/test/plugin/scenarios/tomcat-10x-scenario/config/expectedData.yaml b/test/plugin/scenarios/tomcat-10x-scenario/config/expectedData.yaml index dc03590cdd..030fc841ae 100644 --- a/test/plugin/scenarios/tomcat-10x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/tomcat-10x-scenario/config/expectedData.yaml @@ -34,6 +34,8 @@ segmentItems: tags: - {key: url, value: 'http://localhost:8080/tomcat-10x-scenario/case/tomcat-10x-scenario'} - {key: http.method, value: POST} + - {key: http.params, value: 'q1=[v1]'} + - {key: http.headers, value: 'mock_header=[mock_value]'} - {key: http.status_code, value: "200"} refs: - {parentEndpoint: 'GET:/tomcat-10x-scenario/case/tomcat-10x-scenario', networkAddress: 'localhost:8080', @@ -55,7 +57,7 @@ segmentItems: peer: localhost:8080 skipAnalysis: false tags: - - {key: url, value: 'http://localhost:8080/tomcat-10x-scenario/case/tomcat-10x-scenario'} + - {key: url, value: 'http://localhost:8080/tomcat-10x-scenario/case/tomcat-10x-scenario?q1=v1'} - {key: http.method, value: POST} - {key: http.status_code, value: "200"} - operationName: GET:/tomcat-10x-scenario/case/tomcat-10x-scenario diff --git a/test/plugin/scenarios/tomcat-10x-scenario/configuration.yml b/test/plugin/scenarios/tomcat-10x-scenario/configuration.yml index fac58bdfd1..f28e57d9e7 100644 --- a/test/plugin/scenarios/tomcat-10x-scenario/configuration.yml +++ b/test/plugin/scenarios/tomcat-10x-scenario/configuration.yml @@ -17,3 +17,5 @@ type: tomcat entryService: http://localhost:8080/tomcat-10x-scenario/case/tomcat-10x-scenario healthCheck: http://localhost:8080/tomcat-10x-scenario/case/healthCheck +environment: + - CATALINA_OPTS="-Dskywalking.plugin.http.include_http_headers=mock_header -Dskywalking.plugin.tomcat.collect_http_params=true" diff --git a/test/plugin/scenarios/tomcat-10x-scenario/src/main/java/org/apache/skywalking/apm/testcase/tomcat10x/CaseServlet.java b/test/plugin/scenarios/tomcat-10x-scenario/src/main/java/org/apache/skywalking/apm/testcase/tomcat10x/CaseServlet.java index 441f4e0e0b..78da65ec8a 100644 --- a/test/plugin/scenarios/tomcat-10x-scenario/src/main/java/org/apache/skywalking/apm/testcase/tomcat10x/CaseServlet.java +++ b/test/plugin/scenarios/tomcat-10x-scenario/src/main/java/org/apache/skywalking/apm/testcase/tomcat10x/CaseServlet.java @@ -37,7 +37,10 @@ public class CaseServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost("http://localhost:8080/tomcat-10x-scenario/case/tomcat-10x-scenario"); + // Carry a query param and a header so the receiving Tomcat entry span (doPost) exercises + // the tomcat-plugin's http.params + http.headers collection (see configuration.yml). + HttpPost httpPost = new HttpPost("http://localhost:8080/tomcat-10x-scenario/case/tomcat-10x-scenario?q1=v1"); + httpPost.setHeader("mock_header", "mock_value"); ResponseHandler responseHandler = response -> { HttpEntity entity = response.getEntity(); return entity != null ? EntityUtils.toString(entity) : null; diff --git a/test/plugin/scenarios/tomcat-9x-scenario/config/expectedData.yaml b/test/plugin/scenarios/tomcat-9x-scenario/config/expectedData.yaml index 10bd8bee30..2737cc9ca5 100644 --- a/test/plugin/scenarios/tomcat-9x-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/tomcat-9x-scenario/config/expectedData.yaml @@ -34,6 +34,8 @@ segmentItems: tags: - {key: url, value: 'http://localhost:8080/tomcat-9x-scenario/case/tomcat-9x-scenario'} - {key: http.method, value: POST} + - {key: http.params, value: 'q1=[v1]'} + - {key: http.headers, value: 'mock_header=[mock_value]'} - {key: http.status_code, value: "200"} refs: - {parentEndpoint: 'GET:/tomcat-9x-scenario/case/tomcat-9x-scenario', networkAddress: 'localhost:8080', @@ -55,7 +57,7 @@ segmentItems: peer: localhost:8080 skipAnalysis: false tags: - - {key: url, value: 'http://localhost:8080/tomcat-9x-scenario/case/tomcat-9x-scenario'} + - {key: url, value: 'http://localhost:8080/tomcat-9x-scenario/case/tomcat-9x-scenario?q1=v1'} - {key: http.method, value: POST} - {key: http.status_code, value: "200"} - operationName: GET:/tomcat-9x-scenario/case/tomcat-9x-scenario diff --git a/test/plugin/scenarios/tomcat-9x-scenario/configuration.yml b/test/plugin/scenarios/tomcat-9x-scenario/configuration.yml index 523a817486..b345aba8f7 100644 --- a/test/plugin/scenarios/tomcat-9x-scenario/configuration.yml +++ b/test/plugin/scenarios/tomcat-9x-scenario/configuration.yml @@ -17,3 +17,5 @@ type: tomcat entryService: http://localhost:8080/tomcat-9x-scenario/case/tomcat-9x-scenario healthCheck: http://localhost:8080/tomcat-9x-scenario/case/healthCheck +environment: + - CATALINA_OPTS="-Dskywalking.plugin.http.include_http_headers=mock_header -Dskywalking.plugin.tomcat.collect_http_params=true" diff --git a/test/plugin/scenarios/tomcat-9x-scenario/src/main/java/org/apache/skywalking/apm/testcase/tomcat9x/CaseServlet.java b/test/plugin/scenarios/tomcat-9x-scenario/src/main/java/org/apache/skywalking/apm/testcase/tomcat9x/CaseServlet.java index 9b47be8639..e9dc5969c9 100644 --- a/test/plugin/scenarios/tomcat-9x-scenario/src/main/java/org/apache/skywalking/apm/testcase/tomcat9x/CaseServlet.java +++ b/test/plugin/scenarios/tomcat-9x-scenario/src/main/java/org/apache/skywalking/apm/testcase/tomcat9x/CaseServlet.java @@ -37,7 +37,10 @@ public class CaseServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try (CloseableHttpClient httpClient = HttpClients.createDefault()) { - HttpPost httpPost = new HttpPost("http://localhost:8080/tomcat-9x-scenario/case/tomcat-9x-scenario"); + // Carry a query param and a header so the receiving Tomcat entry span (doPost) exercises + // the tomcat-plugin's http.params + http.headers collection (see configuration.yml). + HttpPost httpPost = new HttpPost("http://localhost:8080/tomcat-9x-scenario/case/tomcat-9x-scenario?q1=v1"); + httpPost.setHeader("mock_header", "mock_value"); ResponseHandler responseHandler = response -> { HttpEntity entity = response.getEntity(); return entity != null ? EntityUtils.toString(entity) : null;