From edc154c40d91f834153c813ace4e02ce7a7b1b56 Mon Sep 17 00:00:00 2001 From: ZhangZhaoyuan Date: Sun, 2 May 2021 11:14:28 +0800 Subject: [PATCH] Add spring cloud gateway 3.x plugin (#6881) --- .github/workflows/plugins-test.3.yaml | 1 + CHANGES.md | 1 + .../gateway-3.x-plugin/pom.xml | 80 ++++++++ ...ClientFinalizerConstructorInterceptor.java | 43 +++++ ...inalizerResponseConnectionInterceptor.java | 77 ++++++++ .../HttpClientFinalizerSendInterceptor.java | 105 +++++++++++ .../HttpClientFinalizerUriInterceptor.java | 52 ++++++ .../v3x/NettyRoutingFilterInterceptor.java | 76 ++++++++ .../AbstractGatewayV3EnhancePluginDefine.java | 32 ++++ .../DispatcherHandlerInstrumentation.java | 32 ++++ .../v3x/define/EnhanceObjectCache.java | 54 ++++++ .../HttpClientFinalizerInstrumentation.java | 121 +++++++++++++ .../NettyRoutingFilterInstrumentation.java | 75 ++++++++ .../ServerWebExchangeInstrumentation.java | 32 ++++ .../src/main/resources/skywalking-plugin.def | 20 ++ ...ntFinalizerConstructorInterceptorTest.java | 70 +++++++ .../HttpClientFinalizerInterceptorTest.java | 171 ++++++++++++++++++ .../cloud/gateway/v3x/MockCliengRequest.java | 125 +++++++++++++ .../cloud/gateway/v3x/MockClientResponse.java | 104 +++++++++++ .../NettyRoutingFilterInterceptorTest.java | 104 +++++++++++ .../optional-spring-cloud/pom.xml | 1 + .../service-agent/java-agent/Plugin-list.md | 1 + .../java-agent/Supported-list.md | 2 +- .../config/expectedData.yaml | 93 ++++++++++ .../gateway-3.x-scenario/configuration.yml | 22 +++ .../gateway-dist/bin/startup.sh | 24 +++ .../gateway-3.x-scenario/gateway-dist/pom.xml | 54 ++++++ .../src/main/assembly/assembly.xml | 46 +++++ .../gateway-projectA-scenario/pom.xml | 67 +++++++ .../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 | 27 +++ .../gateway-projectB-scenario/pom.xml | 57 ++++++ .../sc/gateway/projectB/Application.java | 31 ++++ .../projectB/controller/TestController.java | 35 ++++ .../src/main/resources/application.properties | 17 ++ .../scenarios/gateway-3.x-scenario/pom.xml | 58 ++++++ .../gateway-3.x-scenario/support-version.list | 19 ++ 41 files changed, 2100 insertions(+), 1 deletion(-) create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerConstructorInterceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerResponseConnectionInterceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerSendInterceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerUriInterceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/NettyRoutingFilterInterceptor.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/AbstractGatewayV3EnhancePluginDefine.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/DispatcherHandlerInstrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/EnhanceObjectCache.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/HttpClientFinalizerInstrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/NettyRoutingFilterInstrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/ServerWebExchangeInstrumentation.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerConstructorInterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerInterceptorTest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/MockCliengRequest.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/MockClientResponse.java create mode 100644 apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/NettyRoutingFilterInterceptorTest.java create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/configuration.yml create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/bin/startup.sh create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/pom.xml create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/src/main/assembly/assembly.xml create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/pom.xml create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/pom.xml create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/pom.xml create mode 100644 test/plugin/scenarios/gateway-3.x-scenario/support-version.list diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index edada49a2b..31e8270aaf 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -72,6 +72,7 @@ jobs: - thrift-scenario - dbcp-2.x-scenario - jsonrpc4j-1.x-scenario + - gateway-3.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 46162c06b9..d76142aa23 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -21,6 +21,7 @@ Release Notes. * Add `MessageListener` enhancement in pulsar plugin. * fix a bug that spring-mvc set an error endpoint name if the controller class annotation implements an interface. * Add an optional agent plugin to support mybatis. +* Add `spring-cloud-gateway-3.x` optional plugin. #### OAP-Backend * BugFix: filter invalid Envoy access logs whose socket address is empty. diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml new file mode 100644 index 0000000000..daf23ac323 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/pom.xml @@ -0,0 +1,80 @@ + + + + + + optional-spring-cloud + org.apache.skywalking + 8.6.0-SNAPSHOT + + 4.0.0 + + apm-spring-cloud-gateway-3.x-plugin + jar + http://maven.apache.org + + + 3.0.0 + + + + + org.springframework.cloud + spring-cloud-starter-gateway + ${spring-cloud-starter-gateway.version} + provided + + + org.apache.skywalking + apm-spring-webflux-5.x-plugin + ${project.version} + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + + org.apache.skywalking:apm-spring-webflux-5.x-plugin + + skywalking-plugin.def + + + + + + + + + + + \ No newline at end of file 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/HttpClientFinalizerConstructorInterceptor.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/HttpClientFinalizerConstructorInterceptor.java new file mode 100644 index 0000000000..a082bf58b4 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerConstructorInterceptor.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.v3x; + +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.v3x.define.EnhanceObjectCache; +import reactor.netty.http.client.HttpClientConfig; + +/** + * Intercept the constructor and inject {@link EnhanceObjectCache}. + *

+ * The first constructor argument is {@link reactor.netty.http.client.HttpClientConfig} class instance which can get the + * request uri string. + */ +public class HttpClientFinalizerConstructorInterceptor 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-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerResponseConnectionInterceptor.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/HttpClientFinalizerResponseConnectionInterceptor.java new file mode 100644 index 0000000000..eef52f49ac --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerResponseConnectionInterceptor.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x; + +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.v3x.define.EnhanceObjectCache; +import org.reactivestreams.Publisher; +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 HttpClientFinalizerResponseConnectionInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + 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. Stop the span. + if (cache.getSpan() != null) { + if (response.status().code() >= HttpResponseStatus.BAD_REQUEST.code()) { + cache.getSpan().errorOccurred(); + } + Tags.STATUS_CODE.set(cache.getSpan(), String.valueOf(response.status().code())); + cache.getSpan().asyncFinish(); + } + + if (cache.getSpan1() != null) { + cache.getSpan1().asyncFinish(); + } + return publisher; + }; + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerSendInterceptor.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/HttpClientFinalizerSendInterceptor.java new file mode 100644 index 0000000000..e1c5e35bff --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerSendInterceptor.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x; + +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.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 HttpClientFinalizerSendInterceptor 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; + } + AbstractSpan span = ContextManager.activeSpan(); + 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) throws Throwable { + ((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-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerUriInterceptor.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/HttpClientFinalizerUriInterceptor.java new file mode 100644 index 0000000000..367101e697 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerUriInterceptor.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x; + +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.v3x.define.EnhanceObjectCache; + +import java.lang.reflect.Method; + +/** + * This class intercept uri method to get the url of downstream service + */ +public class HttpClientFinalizerUriInterceptor 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 enhanceObjectCache = (EnhanceObjectCache) ((EnhancedInstance) ret) + .getSkyWalkingDynamicField(); + enhanceObjectCache.setUrl(String.valueOf(allArguments[0])); + } + 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-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/NettyRoutingFilterInterceptor.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/NettyRoutingFilterInterceptor.java new file mode 100644 index 0000000000..cd1331e8e4 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/NettyRoutingFilterInterceptor.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.ServerWebExchangeDecorator; + +import java.lang.reflect.Method; + +import static org.apache.skywalking.apm.network.trace.component.ComponentsDefine.SPRING_CLOUD_GATEWAY; + +/** + * This class intercept filter method. + *

+ * spring-webflux-5.x-plugin will inject context snapshot into skywalking dynamic field, and this + * interceptor will continue the span in another thread. + *

+ */ +public class NettyRoutingFilterInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + 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 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 { + 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-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/AbstractGatewayV3EnhancePluginDefine.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/AbstractGatewayV3EnhancePluginDefine.java new file mode 100644 index 0000000000..bb214e349c --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/AbstractGatewayV3EnhancePluginDefine.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.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 AbstractGatewayV3EnhancePluginDefine extends ClassInstanceMethodsEnhancePluginDefine { + + @Override + protected String[] witnessClasses() { + return new String[]{"org.springframework.cloud.gateway.config.GatewayEnvironmentPostProcessor"}; + } +} 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/DispatcherHandlerInstrumentation.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/DispatcherHandlerInstrumentation.java new file mode 100644 index 0000000000..a789a3de16 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/DispatcherHandlerInstrumentation.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define; + +/** + * This class is used for enable {@link org.apache.skywalking.apm.plugin.spring.webflux.v5.define.DispatcherHandlerInstrumentation} + * class when {@link org.springframework.cloud.gateway.config.GatewayEnvironmentPostProcessor} class is exist + */ +public class DispatcherHandlerInstrumentation extends + org.apache.skywalking.apm.plugin.spring.webflux.v5.define.DispatcherHandlerInstrumentation { + + @Override + protected String[] witnessClasses() { + return new String[]{"org.springframework.cloud.gateway.config.GatewayEnvironmentPostProcessor"}; + } +} 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/EnhanceObjectCache.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/EnhanceObjectCache.java new file mode 100644 index 0000000000..ef5167ddb4 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/EnhanceObjectCache.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.v3x.define; + +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; + +/** + * enhance object cache + */ +public class EnhanceObjectCache { + + private String url; + private AbstractSpan span; + private AbstractSpan span1; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setCacheSpan(AbstractSpan span) { + this.span = span; + } + + public AbstractSpan getSpan() { + return span; + } + + public AbstractSpan getSpan1() { + return span1; + } + + public void setSpan1(final AbstractSpan span) { + span1 = span; + } +} 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/HttpClientFinalizerInstrumentation.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/HttpClientFinalizerInstrumentation.java new file mode 100644 index 0000000000..f5cb9c805b --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/HttpClientFinalizerInstrumentation.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import 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; + +/** + * This class instrument reactor.netty.http.client.HttpClientFinalizer class. + *

+ * This is the class that actually sends the request. By enhancing in different methods, + * we can get information such as uri and send trace context to the downstream service through http header. + *

+ */ +public class HttpClientFinalizerInstrumentation extends AbstractGatewayV3EnhancePluginDefine { + + 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.v3x.HttpClientFinalizerConstructorInterceptor"; + 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.v3x.HttpClientFinalizerUriInterceptor"; + private static final String HTTP_CLIENT_FINALIZER_SEND_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.HttpClientFinalizerSendInterceptor"; + private static final String HTTP_CLIENT_FINALIZER_RESPONSE_CONNECTION_INTERCEPTOR = "org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.HttpClientFinalizerResponseConnectionInterceptor"; + + @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-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/NettyRoutingFilterInstrumentation.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/NettyRoutingFilterInstrumentation.java new file mode 100644 index 0000000000..a40c88d2c6 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/NettyRoutingFilterInstrumentation.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import 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; + +/** + * This class instrument {@link org.springframework.cloud.gateway.filter.NettyRoutingFilter} class. + *

+ * Enhance filter method and get ContextSnapshot from {@link + * org.springframework.web.server.ServerWebExchange}. Create a local span to continue context snapshot created in {@link + * org.apache.skywalking.apm.plugin.spring.webflux.v5.DispatcherHandlerHandleMethodInterceptor} interceptor. + *

+ */ +public class NettyRoutingFilterInstrumentation extends AbstractGatewayV3EnhancePluginDefine { + + 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.v3x.NettyRoutingFilterInterceptor"; + + @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; + } + } + }; + } +} 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/ServerWebExchangeInstrumentation.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/ServerWebExchangeInstrumentation.java new file mode 100644 index 0000000000..a309019eca --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/define/ServerWebExchangeInstrumentation.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define; + +/** + * This class is used for enable {@link org.apache.skywalking.apm.plugin.spring.webflux.v5.define.ServerWebExchangeInstrumentation} + * when {@link org.springframework.cloud.gateway.config.GatewayEnvironmentPostProcessor} class is exist. + */ +public class ServerWebExchangeInstrumentation extends + org.apache.skywalking.apm.plugin.spring.webflux.v5.define.ServerWebExchangeInstrumentation { + + @Override + protected String[] witnessClasses() { + return new String[]{"org.springframework.cloud.gateway.config.GatewayEnvironmentPostProcessor"}; + } +} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..ba4b480501 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +spring-cloud-gateway-3.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.HttpClientFinalizerInstrumentation +spring-cloud-gateway-3.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.NettyRoutingFilterInstrumentation +spring-cloud-gateway-3.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.ServerWebExchangeInstrumentation +spring-cloud-gateway-3.x=org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.DispatcherHandlerInstrumentation diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerConstructorInterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerConstructorInterceptorTest.java new file mode 100644 index 0000000000..f91d5b3859 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerConstructorInterceptorTest.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x.define.EnhanceObjectCache; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import reactor.netty.http.client.HttpClientConfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(HttpClientConfig.class) +public class HttpClientFinalizerConstructorInterceptorTest { + + 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 HttpClientFinalizerConstructorInterceptor httpClientFinalizerConstructorInterceptor; + + @Before + public void setUp() { + httpClientConfig = mock(HttpClientConfig.class); + when(httpClientConfig.uri()).thenReturn(URI); + httpClientFinalizerConstructorInterceptor = new HttpClientFinalizerConstructorInterceptor(); + } + + @Test + public void onConstruct() { + httpClientFinalizerConstructorInterceptor.onConstruct(enhancedInstance, new Object[]{httpClientConfig}); + final EnhanceObjectCache enhanceCache = (EnhanceObjectCache) enhancedInstance.getSkyWalkingDynamicField(); + assertNotNull(enhanceCache); + assertEquals(enhanceCache.getUrl(), URI); + } +} \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerInterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerInterceptorTest.java new file mode 100644 index 0000000000..7723f02d57 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/HttpClientFinalizerInterceptorTest.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x; + +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.v3x.define.EnhanceObjectCache; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.reactivestreams.Publisher; +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(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class HttpClientFinalizerInterceptorTest { + + private final static String URI = "http://localhost:8080/get"; + private final static String ENTRY_OPERATION_NAME = "/get"; + private final HttpClientFinalizerSendInterceptor sendInterceptor = new HttpClientFinalizerSendInterceptor(); + private final HttpClientFinalizerResponseConnectionInterceptor responseConnectionInterceptor = new HttpClientFinalizerResponseConnectionInterceptor(); + 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(); + private HttpClientResponse mockResponse; + private HttpClientRequest mockRequest; + @SegmentStoragePoint + private SegmentStorage segmentStorage; + private AbstractSpan entrySpan; + + @Before + public void setUp() throws Exception { + final EnhanceObjectCache enhanceObjectCache = new EnhanceObjectCache(); + enhanceObjectCache.setUrl(URI); + enhancedInstance.setSkyWalkingDynamicField(enhanceObjectCache); + entrySpan = ContextManager.createEntrySpan(ENTRY_OPERATION_NAME, null); + entrySpan.setLayer(SpanLayer.HTTP); + entrySpan.setComponent(ComponentsDefine.SPRING_WEBFLUX); + mockRequest = new MockCliengRequest(); + mockResponse = new MockClientResponse(); + } + + @Test + public void testWithDynamicFieldNull() throws Throwable { + enhancedInstance.setSkyWalkingDynamicField(null); + executeSendRequest(); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 0); + if (ContextManager.isActive()) { + ContextManager.stopSpan(); + } + } + + @Test + public void testWithEmptyUri() throws Throwable { + final EnhanceObjectCache objectCache = (EnhanceObjectCache) enhancedInstance.getSkyWalkingDynamicField(); + objectCache.setUrl(""); + executeSendRequest(); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 1); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + assertNotNull(spans); + assertEquals(spans.size(), 1); + assertUpstreamSpan(spans.get(0)); + assertNotNull(objectCache.getSpan1()); + assertEquals(objectCache.getSpan1().getSpanId(), entrySpan.getSpanId()); + } + + @Test + public void testWithUri() throws Throwable { + executeSendRequest(); + final List traceSegments = segmentStorage.getTraceSegments(); + assertEquals(traceSegments.size(), 1); + final EnhanceObjectCache objectCache = (EnhanceObjectCache) enhancedInstance + .getSkyWalkingDynamicField(); + assertNotNull(objectCache.getSpan1()); + assertNotNull(objectCache.getSpan()); + assertEquals(objectCache.getSpan1().getSpanId(), entrySpan.getSpanId()); + assertTrue(objectCache.getSpan().isExit()); + assertEquals(objectCache.getSpan().getOperationName(), "SpringCloudGateway/sendRequest"); + final List spans = SegmentHelper.getSpans(traceSegments.get(0)); + assertNotNull(spans); + assertEquals(spans.size(), 2); + assertUpstreamSpan(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); + responseConnectionInterceptor.afterMethod(enhancedInstance, null, new Object[0], null, enhancedInstance); + ((BiFunction>) responseConnectionArguments[0]) + .apply(mockResponse, null); + } + + private void assertUpstreamSpan(AbstractSpan span) { + SpanAssert.assertLayer(span, SpanLayer.HTTP); + SpanAssert.assertComponent(span, ComponentsDefine.SPRING_WEBFLUX); + } + + 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())); + } +} \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/MockCliengRequest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/MockCliengRequest.java new file mode 100644 index 0000000000..e36ff81f86 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/MockCliengRequest.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.v3x; + +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 MockCliengRequest 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 fullPath() { + 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-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/MockClientResponse.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/MockClientResponse.java new file mode 100644 index 0000000000..d287d3afe6 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/MockClientResponse.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x; + +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.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 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 fullPath() { + 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-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/NettyRoutingFilterInterceptorTest.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/NettyRoutingFilterInterceptorTest.java new file mode 100644 index 0000000000..3b42214623 --- /dev/null +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v3x/NettyRoutingFilterInterceptorTest.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v3x; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.helper.SegmentHelper; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.SpanAssert; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; + +import java.util.List; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class NettyRoutingFilterInterceptorTest { + + private final EnhancedInstance enhancedInstance = new EnhancedInstance() { + private ContextSnapshot snapshot; + + @Override + public Object getSkyWalkingDynamicField() { + return snapshot; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.snapshot = (ContextSnapshot) value; + } + }; + private final NettyRoutingFilterInterceptor interceptor = new NettyRoutingFilterInterceptor(); + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + @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); + 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); + 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); + } +} \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml index b9b5bc3ed8..9ce95cf5ee 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/pom.xml @@ -30,6 +30,7 @@ gateway-2.0.x-plugin gateway-2.1.x-plugin + gateway-3.x-plugin pom diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md b/docs/en/setup/service-agent/java-agent/Plugin-list.md index 09c841ed31..a29d325572 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -116,3 +116,4 @@ - mssql-jdbc - apache-cxf-3.x - jsonrpc4j +- spring-cloud-gateway-3.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 0fa090c2bd..e5a9501f2b 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -30,7 +30,7 @@ metrics based on the tracing data. * [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client) 2.x * JRE HttpURLConnection (Optional²) * HTTP Gateway - * [Spring Cloud Gateway](https://spring.io/projects/spring-cloud-gateway) 2.0.2.RELEASE -> 2.2.x.RELEASE (Optional²) + * [Spring Cloud Gateway](https://spring.io/projects/spring-cloud-gateway) 2.0.2.RELEASE -> 3.x (Optional²) * JDBC * Mysql Driver 5.x, 6.x, 8.x * Oracle Driver (Optional¹) diff --git a/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..bdc66a31e6 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/config/expectedData.yaml @@ -0,0 +1,93 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +segmentItems: +- serviceName: gateway-projectB-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: /provider/b/testcase + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: nq 0 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: not null} + - {key: http.method, value: GET} + refs: + - {parentEndpoint: SpringCloudGateway/RoutingFilter, 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/b/testcase + operationId: 0 + 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: status_code, value: '200'} + skipAnalysis: 'false' + - segmentId: not null + spans: + - operationName: SpringCloudGateway/sendRequest + operationId: 0 + 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: status_code, value: '200'} + skipAnalysis: 'false' + - operationName: SpringCloudGateway/RoutingFilter + operationId: 0 + parentSpanId: -1 + spanId: 0 + startTime: nq 0 + endTime: nq 0 + componentId: 61 + isError: false + spanType: Local + peer: '' + refs: + - {parentEndpoint: '/provider/b/testcase', networkAddress: '', refType: CrossThread, + parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not + null, parentService: not null, traceId: not null} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/gateway-3.x-scenario/configuration.yml b/test/plugin/scenarios/gateway-3.x-scenario/configuration.yml new file mode 100644 index 0000000000..67b623799d --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/configuration.yml @@ -0,0 +1,22 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +type: jvm +entryService: http://localhost:8080/provider/b/testcase +healthCheck: http://localhost:8080/provider/b/healthCheck +startScript: ./bin/startup.sh +runningMode: with_optional +withPlugins: apm-spring-cloud-gateway-3.x-plugin-*.jar diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/bin/startup.sh b/test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/bin/startup.sh new file mode 100644 index 0000000000..0d28675632 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/bin/startup.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +home="$(cd "$(dirname $0)"; pwd)" + +java -jar ${agent_opts} "-Dskywalking.agent.service_name=gateway-projectA-scenario" ${home}/../libs/gateway-projectA-scenario.jar & +sleep 1 + +java -jar ${agent_opts} "-Dskywalking.agent.service_name=gateway-projectB-scenario" ${home}/../libs/gateway-projectB-scenario.jar & diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/pom.xml b/test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/pom.xml new file mode 100644 index 0000000000..549ecbb168 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/pom.xml @@ -0,0 +1,54 @@ + + + + + org.apache.skywalking + gateway-3.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-3.x-scenario/gateway-dist/src/main/assembly/assembly.xml b/test/plugin/scenarios/gateway-3.x-scenario/gateway-dist/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..00d04e28e0 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.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-3.x-scenario/gateway-projectA-scenario/pom.xml b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/pom.xml new file mode 100644 index 0000000000..82ac0fb558 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/pom.xml @@ -0,0 +1,67 @@ + + + + + org.apache.skywalking + gateway-3.x-scenario + 5.0.0 + + 4.0.0 + + gateway-projectA-scenario + + + + org.springframework.cloud + spring-cloud-starter-gateway + ${test.framework.version} + + + + + gateway-projectA-scenario + + + org.springframework.boot + spring-boot-maven-plugin + 1.5.9.RELEASE + + + + repackage + + + + + + + + + + spring-snapshots + https://repo.spring.io/snapshot + + + spring-milestones + https://repo.spring.io/milestone + + + diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java new file mode 100644 index 0000000000..40517d1d3f --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/ApiKeyResolver.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.apache.skywalking.apm.testcase.sc.gateway.projectA; + +import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; +import org.springframework.stereotype.Component; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +@Component +public class ApiKeyResolver implements KeyResolver { + + public Mono resolve(ServerWebExchange exchange) { + return Mono.just(exchange.getRequest().getPath().value()); + } +} diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java new file mode 100644 index 0000000000..68eb95b0c6 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Application.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.apache.skywalking.apm.testcase.sc.gateway.projectA; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java new file mode 100644 index 0000000000..af891eae20 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test1Filter.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.apache.skywalking.apm.testcase.sc.gateway.projectA; + +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +public class Test1Filter implements GlobalFilter, Ordered { + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest buildRequest = exchange.getRequest().mutate().build(); + return chain.filter(exchange.mutate().request(buildRequest).build()); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java new file mode 100644 index 0000000000..d3a5846bd5 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/Test2Filter.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.apache.skywalking.apm.testcase.sc.gateway.projectA; + +import org.springframework.cloud.gateway.filter.GatewayFilterChain; +import org.springframework.cloud.gateway.filter.GlobalFilter; +import org.springframework.core.Ordered; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +public class Test2Filter implements GlobalFilter, Ordered { + + @Override + public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest buildRequest = exchange.getRequest().mutate().build(); + return chain.filter(exchange.mutate().request(buildRequest).build()); + } + + @Override + public int getOrder() { + return 1; + } +} diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java new file mode 100644 index 0000000000..29f9627bdf --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectA/TestFilterConfig.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.apache.skywalking.apm.testcase.sc.gateway.projectA; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class TestFilterConfig { + + @Bean + public Test1Filter test1Filter() { + return new Test1Filter(); + } + + @Bean + public Test2Filter test2Filter() { + return new Test2Filter(); + } +} diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml new file mode 100644 index 0000000000..da55c58a41 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectA-scenario/src/main/resources/application.yml @@ -0,0 +1,27 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +server: + port: 8080 +spring: + cloud: + gateway: + routes: + - id: provider_route + uri: http://localhost:18070 + predicates: + - Path=/provider/b/* diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/pom.xml b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/pom.xml new file mode 100644 index 0000000000..28513d424c --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/pom.xml @@ -0,0 +1,57 @@ + + + + + gateway-3.x-scenario + org.apache.skywalking + 5.0.0 + + 4.0.0 + + gateway-projectB-scenario + + + + org.springframework.boot + spring-boot-starter-web + 2.1.0.RELEASE + + + + + gateway-projectB-scenario + + + org.springframework.boot + spring-boot-maven-plugin + 1.5.9.RELEASE + + + + repackage + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java new file mode 100644 index 0000000000..51c94655c7 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/Application.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package test.apache.skywalking.apm.testcase.sc.gateway.projectB; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(value = {"test.apache.skywalking.apm.testcase.sc.gateway.projectB.controller"}) +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.java new file mode 100644 index 0000000000..cb8b88ebad --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/gateway/projectB/controller/TestController.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.projectB.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestController { + + @RequestMapping("/provider/b/testcase") + public String testcase() { + return "1"; + } + + @RequestMapping("/provider/b/healthCheck") + public String healthCheck() { + return "Success"; + } +} diff --git a/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties new file mode 100644 index 0000000000..cac2c4d5a1 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/gateway-projectB-scenario/src/main/resources/application.properties @@ -0,0 +1,17 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +server.port=18070 \ No newline at end of file diff --git a/test/plugin/scenarios/gateway-3.x-scenario/pom.xml b/test/plugin/scenarios/gateway-3.x-scenario/pom.xml new file mode 100644 index 0000000000..9f87f3f7a9 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.x-scenario/pom.xml @@ -0,0 +1,58 @@ + + + + 4.0.0 + + org.apache.skywalking + gateway-3.x-scenario + pom + 5.0.0 + + gateway-projectA-scenario + gateway-projectB-scenario + gateway-dist + + + skywalking-gateway-3.x-scenario + + + UTF-8 + 3.0.0 + ${test.framework.version} + + + + gateway-3.x-scenario + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.0 + + 1.8 + 1.8 + ${project.build.sourceEncoding} + + + + + + diff --git a/test/plugin/scenarios/gateway-3.x-scenario/support-version.list b/test/plugin/scenarios/gateway-3.x-scenario/support-version.list new file mode 100644 index 0000000000..5f14207b14 --- /dev/null +++ b/test/plugin/scenarios/gateway-3.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. + +3.0.0 +3.0.1 +3.0.2 \ No newline at end of file -- GitLab