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] [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