diff --git a/.github/workflows/plugins-test.yaml b/.github/workflows/plugins-test.yaml index 9cb28d526..99edb7856 100644 --- a/.github/workflows/plugins-test.yaml +++ b/.github/workflows/plugins-test.yaml @@ -106,7 +106,7 @@ jobs: run: ./mvnw -f test/plugin/pom.xml clean package -DskipTests docker:build -DBUILD_NO=local >/dev/null - name: Run apm-toolkit-trace (1) run: bash test/plugin/run.sh apm-toolkit-trace-scenario - - name: Run spring-webflux 2.x (18) + - name: Run spring-webflux 2.x (7) run: bash test/plugin/run.sh webflux-scenario - name: Run netty-socketio 1.x (4) run: bash test/plugin/run.sh netty-socketio-scenario diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml index cbc177973..5eca22226 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml @@ -38,7 +38,6 @@ mvc-annotation-commons spring-commons mvc-annotation-5.x-plugin - webflux-5.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/AbstractServerResponseMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/AbstractServerResponseMethodInterceptor.java deleted file mode 100644 index 13162c70f..000000000 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/AbstractServerResponseMethodInterceptor.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.spring.webflux.v5; - -/** - * @author zhaoyuguang - */ - -import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.context.tag.Tags; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; -import org.springframework.http.HttpStatus; -import org.springframework.web.server.ServerWebExchange; - -import java.lang.reflect.Method; - -public class AbstractServerResponseMethodInterceptor implements InstanceMethodsAroundInterceptor { - - /** - * The error reason - * see more details org.springframework.boot.web.reactive.error.DefaultErrorAttributes#storeErrorInformation - */ - private final static String ERROR_ATTRIBUTE = "org.springframework.boot.web.reactive.error.DefaultErrorAttributes.ERROR"; - - @Override - public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { - EnhancedInstance instance = DispatcherHandlerHandleMethodInterceptor.getInstance(allArguments[0]); - if (instance != null) { - AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField(); - if (span == null) { - return; - } - ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; - HttpStatus status = exchange.getResponse().getStatusCode(); - if (status != null && status.value() >= 400) { - span.errorOccurred(); - if (exchange.getAttribute(ERROR_ATTRIBUTE) != null) { - span.log((Throwable) exchange.getAttribute(ERROR_ATTRIBUTE)); - } - Tags.STATUS_CODE.set(span, Integer.toString(status.value())); - } - if (ContextManager.isActive()) { - ContextManager.stopSpan(span); - } else { - span.asyncFinish(); - } - ((EnhancedInstance) allArguments[0]).setSkyWalkingDynamicField(null); - } - } - - @Override - public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { - return ret; - } - - @Override - public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Throwable t) { - - } -} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleResultMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleResultMethodInterceptor.java deleted file mode 100644 index 79a97e670..000000000 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleResultMethodInterceptor.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.spring.webflux.v5; - -/** - * @author zhaoyuguang - */ - -import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; - -import java.lang.reflect.Method; - -public class DispatcherHandlerHandleResultMethodInterceptor 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 { - EnhancedInstance instance = DispatcherHandlerHandleMethodInterceptor.getInstance(allArguments[0]); - if (instance != null) { - AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField(); - if (span != null) { - ContextManager.stopSpan(span); - instance.setSkyWalkingDynamicField(null); - } - } - return ret; - } - - @Override - public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t) { - } -} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerInvokeHandlerMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerInvokeHandlerMethodInterceptor.java deleted file mode 100644 index 542e82a88..000000000 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerInvokeHandlerMethodInterceptor.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.spring.webflux.v5; - -/** - * @author zhaoyuguang - */ - -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.method.HandlerMethod; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -public class DispatcherHandlerInvokeHandlerMethodInterceptor implements InstanceMethodsAroundInterceptor { - - private static final String ROUTER_SEARCH = "$$Lambda"; - private static final String ROUTER_FIELD = "arg$1"; - private static final String DOT = "."; - - - @Override - public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { - EnhancedInstance instance = DispatcherHandlerHandleMethodInterceptor.getInstance(allArguments[0]); - if (instance != null) { - AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField(); - if (span == null) { - return; - } - String handleClassName = allArguments[1].getClass().getSimpleName(); - int index = handleClassName.indexOf(ROUTER_SEARCH); - if (index != -1) { - String operationName = handleClassName.substring(0, index); - try { - Field field = allArguments[1].getClass().getDeclaredField(ROUTER_FIELD); - field.setAccessible(true); - operationName = operationName + DOT + field.get(allArguments[1]).getClass().getName(); - } catch (NoSuchFieldException ignore) { - } - span.setOperationName(operationName); - } else if (allArguments[1] instanceof HandlerMethod) { - HandlerMethod handler = (HandlerMethod) allArguments[1]; - span.setOperationName(getHandlerMethodOperationName(handler)); - } - } - } - - @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) { - } - - private String getHandlerMethodOperationName(HandlerMethod handler) { - Method method = handler.getMethod(); - return method.getDeclaringClass().getName() + DOT + method.getName(); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/AbstractServerResponseInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/AbstractServerResponseInstrumentation.java deleted file mode 100644 index 686affb51..000000000 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/AbstractServerResponseInstrumentation.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.spring.webflux.v5.define; - -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; -import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; - -import static net.bytebuddy.matcher.ElementMatchers.named; -import static org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch.byMultiClassMatch; - -/** - * @author zhaoyuguang - */ - -public class AbstractServerResponseInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { - - @Override - protected ClassMatch enhanceClass() { - return byMultiClassMatch("org.springframework.web.reactive.function.server.DefaultServerResponseBuilder$BodyInserterResponse", - "org.springframework.web.reactive.function.server.DefaultServerResponseBuilder$BodyInserterServerResponse", - "org.springframework.web.reactive.function.server.DefaultEntityResponseBuilder$DefaultEntityResponse"); - } - - @Override - public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[0]; - } - - @Override - public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[] { - new InstanceMethodsInterceptPoint() { - @Override public ElementMatcher getMethodsMatcher() { - return named("writeToInternal"); - } - - @Override public String getMethodsInterceptor() { - return "org.apache.skywalking.apm.plugin.spring.webflux.v5.AbstractServerResponseMethodInterceptor"; - } - - @Override public boolean isOverrideArgs() { - return false; - } - } - }; - } -} diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/FilteringWebHandlerInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/FilteringWebHandlerInterceptor.java index 9eb1bd0f7..427e982bc 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/FilteringWebHandlerInterceptor.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/FilteringWebHandlerInterceptor.java @@ -18,7 +18,11 @@ package org.apache.skywalking.apm.plugin.spring.cloud.gateway.v21x; +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR; + +import java.lang.reflect.Method; import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; import org.apache.skywalking.apm.agent.core.context.tag.Tags; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; @@ -31,9 +35,6 @@ import org.springframework.cloud.gateway.route.Route; import org.springframework.http.HttpStatus; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; -import java.lang.reflect.Method; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR; /** @@ -42,6 +43,7 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.G public class FilteringWebHandlerInterceptor implements InstanceMethodsAroundInterceptor { private static final String SPRING_CLOUD_GATEWAY_ROUTE_PREFIX = "GATEWAY/"; + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { @@ -49,18 +51,17 @@ public class FilteringWebHandlerInterceptor implements InstanceMethodsAroundInte if (instance == null) { return; } - AbstractSpan span = (AbstractSpan) instance.getSkyWalkingDynamicField(); - if (span == null) { + ContextSnapshot contextSnapshot = (ContextSnapshot) instance.getSkyWalkingDynamicField(); + if (contextSnapshot == null) { return; } + ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; String operationName = SPRING_CLOUD_GATEWAY_ROUTE_PREFIX; Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR); operationName = operationName + route.getId(); - span.setOperationName(operationName); - SWTransmitter transmitter = new SWTransmitter(span.prepareForAsync(),ContextManager.capture(),operationName); + SWTransmitter transmitter = new SWTransmitter(contextSnapshot, operationName); instance.setSkyWalkingDynamicField(transmitter); - ContextManager.stopSpan(span); } @Override @@ -85,8 +86,6 @@ public class FilteringWebHandlerInterceptor implements InstanceMethodsAroundInte localSpan.setComponent(ComponentsDefine.SPRING_CLOUD_GATEWAY); ContextManager.continued(swTransmitter.getSnapshot()); ContextManager.stopSpan(localSpan); - AbstractSpan spanWebflux = swTransmitter.getSpanWebflux(); - spanWebflux.asyncFinish(); } }); } diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientOperationsStatusInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientOperationsStatusInterceptor.java index 89ff18015..6324308b8 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientOperationsStatusInterceptor.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/HttpClientOperationsStatusInterceptor.java @@ -48,10 +48,8 @@ public class HttpClientOperationsStatusInterceptor implements InstanceMethodsAro HttpResponseStatus response = (HttpResponseStatus) ret; if (response.code() >= 400) { Tags.STATUS_CODE.set(transmitter.getSpanGateway().errorOccurred(), String.valueOf(response.code())); - Tags.STATUS_CODE.set(transmitter.getSpanWebflux().errorOccurred(), String.valueOf(response.code())); } transmitter.getSpanGateway().asyncFinish(); - transmitter.getSpanWebflux().asyncFinish(); objInst.setSkyWalkingDynamicField(null); } return ret; diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/context/SWTransmitter.java b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/context/SWTransmitter.java index bedd4891f..216dd2292 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/context/SWTransmitter.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/optional-spring-cloud/gateway-2.1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/cloud/gateway/v21x/context/SWTransmitter.java @@ -27,25 +27,15 @@ import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; public class SWTransmitter { - private AbstractSpan spanWebflux; private AbstractSpan spanGateway; private ContextSnapshot snapshot; private String operationName; - public SWTransmitter(AbstractSpan spanWebflux, ContextSnapshot snapshot, String operationName) { - this.spanWebflux = spanWebflux; + public SWTransmitter(ContextSnapshot snapshot, String operationName) { this.snapshot = snapshot; this.operationName = operationName; } - public AbstractSpan getSpanWebflux() { - return spanWebflux; - } - - public void setSpanWebflux(AbstractSpan spanWebflux) { - this.spanWebflux = spanWebflux; - } - public AbstractSpan getSpanGateway() { return spanGateway; } diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml index 3284106e1..f64764f68 100644 --- a/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/pom.xml @@ -32,10 +32,11 @@ spring-annotation-plugin spring-tx-plugin optional-spring-cloud + spring-webflux-5.x-plugin /.. - \ No newline at end of file + diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/pom.xml b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml similarity index 64% rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/pom.xml rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml index 44edf24b1..b47693798 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/pom.xml @@ -1,3 +1,4 @@ + - + - spring-plugins + optional-spring-plugins org.apache.skywalking 6.6.0-SNAPSHOT 4.0.0 - apm-webflux-5.x-plugin - jar + apm-spring-webflux-5.x-plugin - webflux-5.x-plugin http://maven.apache.org @@ -37,4 +39,8 @@ provided + + + 1.8 + diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java similarity index 55% rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java index 712ca6569..26f94ce1c 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/DispatcherHandlerHandleMethodInterceptor.java @@ -18,14 +18,13 @@ package org.apache.skywalking.apm.plugin.spring.webflux.v5; -/** - * @author zhaoyuguang - */ - +import java.lang.reflect.Method; +import java.util.List; 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.tag.Tags.HTTP; 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; @@ -33,45 +32,72 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceM import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchangeDecorator; import org.springframework.web.server.adapter.DefaultServerWebExchange; +import org.springframework.web.util.pattern.PathPattern; +import reactor.core.publisher.Mono; -import java.lang.reflect.Method; -import java.util.List; - +/** + * @author zhaoyuguang, Born + */ public class DispatcherHandlerHandleMethodInterceptor implements InstanceMethodsAroundInterceptor { - - private static final String WIP_OPERATION_NAME = "WEBFLUX.handle"; + private static final String DEFAULT_OPERATION_NAME = "WEBFLUX.handle"; @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { - EnhancedInstance instance = DispatcherHandlerHandleMethodInterceptor.getInstance(allArguments[0]); - if (instance != null) { - ContextCarrier contextCarrier = new ContextCarrier(); - CarrierItem next = contextCarrier.items(); - ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; - HttpHeaders headers = exchange.getRequest().getHeaders(); - while (next.hasNext()) { - next = next.next(); - List header = headers.get(next.getHeadKey()); - if (header != null && header.size() > 0) { - next.setHeadValue(header.get(0)); - } - } - AbstractSpan span = ContextManager.createEntrySpan(WIP_OPERATION_NAME, contextCarrier); - span.setComponent(ComponentsDefine.SPRING_WEBFLUX); - SpanLayer.asHttp(span); - Tags.URL.set(span, exchange.getRequest().getURI().toString()); - instance.setSkyWalkingDynamicField(span); - } + } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, Object ret) throws Throwable { - return ret; + EnhancedInstance instance = getInstance(allArguments[0]); + + ServerWebExchange exchange = (ServerWebExchange) allArguments[0]; + + ContextCarrier carrier = new ContextCarrier(); + CarrierItem next = carrier.items(); + HttpHeaders headers = exchange.getRequest().getHeaders(); + while (next.hasNext()) { + next = next.next(); + List header = headers.get(next.getHeadKey()); + if (header != null && header.size() > 0) { + next.setHeadValue(header.get(0)); + } + } + + AbstractSpan span = ContextManager.createEntrySpan(DEFAULT_OPERATION_NAME, carrier); + span.setComponent(ComponentsDefine.SPRING_WEBFLUX); + SpanLayer.asHttp(span); + Tags.URL.set(span, exchange.getRequest().getURI().toString()); + HTTP.METHOD.set(span, exchange.getRequest().getMethodValue()); + instance.setSkyWalkingDynamicField(ContextManager.capture()); + span.prepareForAsync(); + ContextManager.stopSpan(span); + + return ((Mono) ret).doFinally(s -> { + try { + Object pathPattern = exchange.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); + if (pathPattern != null) { + span.setOperationName(((PathPattern) pathPattern).getPatternString()); + } + HttpStatus httpStatus = exchange.getResponse().getStatusCode(); + // fix webflux-2.0.0-2.1.0 version have bug. httpStatus is null. not support + if (httpStatus != null) { + Tags.STATUS_CODE.set(span, Integer.toString(httpStatus.value())); + if (httpStatus.isError()) { + span.errorOccurred(); + } + } + } finally { + span.asyncFinish(); + } + }); + } @Override @@ -81,26 +107,13 @@ public class DispatcherHandlerHandleMethodInterceptor implements InstanceMethods public static EnhancedInstance getInstance(Object o) { EnhancedInstance instance = null; - if (o instanceof ServerWebExchangeDecorator) { - instance = getEnhancedInstance((ServerWebExchangeDecorator) o); - } else if (o instanceof DefaultServerWebExchange) { + if (o instanceof DefaultServerWebExchange) { instance = (EnhancedInstance) o; + } else if (o instanceof ServerWebExchangeDecorator) { + ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate(); + return getInstance(delegate); } return instance; } - - private static EnhancedInstance getEnhancedInstance(ServerWebExchangeDecorator serverWebExchangeDecorator) { - Object o = serverWebExchangeDecorator.getDelegate(); - if (o instanceof ServerWebExchangeDecorator) { - return getEnhancedInstance((ServerWebExchangeDecorator) o); - } else if (o instanceof DefaultServerWebExchange) { - return (EnhancedInstance) o; - } else if (o == null) { - throw new NullPointerException("The expected class DefaultServerWebExchange is null"); - } else { - throw new RuntimeException("Unknown parameter types:" + o.getClass()); - } - } - } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java similarity index 97% rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java index f6b805f25..6df67c842 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/ServerWebExchangeConstructorInterceptor.java @@ -23,7 +23,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceC /** * - * @author zhaoyuguang + * @author zhaoyuguang, Born */ public class ServerWebExchangeConstructorInterceptor implements InstanceConstructorInterceptor { @Override diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java similarity index 68% rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java index 6113b8abe..a6451177f 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/DispatcherHandlerInstrumentation.java @@ -29,7 +29,7 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; /** - * @author zhaoyuguang + * @author zhaoyuguang, Born */ public class DispatcherHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { @@ -52,36 +52,6 @@ public class DispatcherHandlerInstrumentation extends ClassInstanceMethodsEnhanc return "org.apache.skywalking.apm.plugin.spring.webflux.v5.DispatcherHandlerHandleMethodInterceptor"; } - @Override - public boolean isOverrideArgs() { - return false; - } - }, new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("invokeHandler"); - } - - @Override - public String getMethodsInterceptor() { - return "org.apache.skywalking.apm.plugin.spring.webflux.v5.DispatcherHandlerInvokeHandlerMethodInterceptor"; - } - - @Override - public boolean isOverrideArgs() { - return false; - } - }, new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("handleResult"); - } - - @Override - public String getMethodsInterceptor() { - return "org.apache.skywalking.apm.plugin.spring.webflux.v5.DispatcherHandlerHandleResultMethodInterceptor"; - } - @Override public boolean isOverrideArgs() { return false; diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java similarity index 98% rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java index 0efe4025f..e4d0e3040 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/define/ServerWebExchangeInstrumentation.java @@ -29,9 +29,8 @@ import static net.bytebuddy.matcher.ElementMatchers.any; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; /** - * @author zhaoyuguang + * @author zhaoyuguang, Born */ - public class ServerWebExchangeInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/resources/skywalking-plugin.def similarity index 89% rename from apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/resources/skywalking-plugin.def rename to apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/resources/skywalking-plugin.def index f1752e3f7..278cd044e 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/webflux-5.x-plugin/src/main/resources/skywalking-plugin.def +++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-webflux-5.x-plugin/src/main/resources/skywalking-plugin.def @@ -16,4 +16,3 @@ spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.DispatcherHandlerInstrumentation spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.ServerWebExchangeInstrumentation -spring-webflux-5.x=org.apache.skywalking.apm.plugin.spring.webflux.v5.define.AbstractServerResponseInstrumentation \ No newline at end of file diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md index c316651ba..bd03984f0 100755 --- a/docs/en/setup/service-agent/java-agent/README.md +++ b/docs/en/setup/service-agent/java-agent/README.md @@ -131,9 +131,10 @@ Now, we have the following known optional plugins. * Plugin of Lettuce 5.x(JRE 8+) in optional plugin folder. Agent is compatible in JDK 1.6+, this plugin could be used in JRE 8+, by matching the lib requirement. * Plugin of Zookeeper 3.4.x in optional plugin folder. The reason of being optional plugin is, many business irrelevant traces are generated, which cause extra payload to agents and backends. At the same time, those traces may be just heartbeat(s). * [Customize enhance](Customize-enhance-trace.md) Trace methods based on description files, rather than write plugin or change source codes. -* Plugin of Spring Cloud Gateway 2.1.x in optional plugin folder. Please only active this plugin when you install agent in Spring Gateway. +* Plugin of Spring Cloud Gateway 2.1.x in optional plugin folder. Please only active this plugin when you install agent in Spring Gateway. spring-cloud-gateway-2.x-plugin and spring-webflux-5.x-plugin are both required. * Plugin of [Play Framework](https://www.playframework.com/) 2.6+ (JDK 1.8 required & Scala 2.12/2.13) in optional plugin folder. Please only active this plugin when you install agent in [Play Framework](https://www.playframework.com/). * Plugin of Spring Transaction in optional plugin folder. The reason of being optional plugin is, many local span are generated, which also spend more CPU, memory and network. +* Plugin of Spring Webflux 5.x in the optional plugin folder. Because the plugin requires JDK 1.8+. ## Bootstrap class plugins All bootstrap plugins are optional, due to unexpected risk. Bootstrap plugins are provided in `bootstrap-plugins` folder. 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 a9c12b464..2e1ad4c81 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -9,7 +9,7 @@ * [Resin](http://www.caucho.com/resin-4.0/) 3 (Optional¹) * [Resin](http://www.caucho.com/resin-4.0/) 4 (Optional¹) * [Jetty Server](http://www.eclipse.org/jetty/) 9 - * [Spring Webflux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) 5.x + * [Spring Webflux](https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html) 5.x (Optional²) * [Undertow](http://undertow.io/) 1.3.0.Final -> 2.0.27.Final * [RESTEasy](https://resteasy.github.io/) 3.1.0.Final -> 3.7.0.Final * [Play Framework](https://www.playframework.com/) 2.6.x -> 2.7.x (Optional²) diff --git a/test/plugin/scenarios/gateway-scenario/config/expectedData.yaml b/test/plugin/scenarios/gateway-scenario/config/expectedData.yaml index 6d8e834df..395be6df9 100644 --- a/test/plugin/scenarios/gateway-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/gateway-scenario/config/expectedData.yaml @@ -22,8 +22,8 @@ registryItems: - {gateway-projectB-scenario: 1} - {gateway-projectA-scenario: 1} operationNames: - - gateway-projectB-scenario: [/provider/b/healthCheck, /provider/b/testcase] - - gateway-projectA-scenario: [GATEWAY/provider_route] + - gateway-projectB-scenario: [/provider/b/testcase] + - gateway-projectA-scenario: [WEBFLUX.handle] heartbeat: [] segmentItems: - applicationCode: gateway-projectB-scenario @@ -47,6 +47,11 @@ segmentItems: tags: - {key: url, value: not null} - {key: http.method, value: GET} + refs: + - {parentEndpointId: -1, parentEndpoint: '', networkAddressId: 0, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: not null, networkAddress: 'localhost:18070', entryEndpoint: WEBFLUX.handle, + entryServiceInstanceId: not null} - applicationCode: gateway-projectA-scenario segmentSize: nq 0 segments: @@ -69,13 +74,13 @@ segmentItems: - {key: url, value: not null} - {key: http.method, value: GET} refs: - - {parentEndpointId: 0, parentEndpoint: GATEWAY/provider_route, networkAddressId: 0, + - {parentEndpointId: 0, parentEndpoint: WEBFLUX.handle, networkAddressId: 0, entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, - parentServiceInstanceId: not null, networkAddress: '', entryEndpoint: GATEWAY/provider_route, + parentServiceInstanceId: not null, networkAddress: '', entryEndpoint: WEBFLUX.handle, entryServiceInstanceId: not null} - segmentId: not null spans: - - operationName: GATEWAY/provider_route + - operationName: WEBFLUX.handle operationId: 0 parentSpanId: -1 spanId: 0 @@ -89,4 +94,6 @@ segmentItems: peer: '' peerId: 0 tags: - - {key: url, value: not null} \ No newline at end of file + - {key: url, value: 'http://localhost:8080/provider/b/testcase'} + - {key: http.method, value: GET} + - {key: status_code, value: '200'} diff --git a/test/plugin/scenarios/gateway-scenario/configuration.yml b/test/plugin/scenarios/gateway-scenario/configuration.yml index 40409eb26..4aa0945bf 100644 --- a/test/plugin/scenarios/gateway-scenario/configuration.yml +++ b/test/plugin/scenarios/gateway-scenario/configuration.yml @@ -20,4 +20,4 @@ healthCheck: http://localhost:8080/provider/b/healthCheck startScript: ./bin/startup.sh framework: spring-cloud-gateway runningMode: with_optional -withPlugins: apm-spring-cloud-gateway-2.x-plugin-*.jar +withPlugins: apm-spring-cloud-gateway-2.x-plugin-*.jar;apm-spring-webflux-5.x-plugin-*.jar diff --git a/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/pom.xml b/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/pom.xml index 99654a6a7..23935dac2 100644 --- a/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/pom.xml +++ b/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/pom.xml @@ -39,6 +39,7 @@ spring-boot-starter-data-redis 2.1.2.RELEASE + @@ -69,4 +70,4 @@ http://repo.spring.io/milestone - \ No newline at end of file + diff --git a/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/src/main/resources/application.yml b/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/src/main/resources/application.yml index 00e8ee3d8..ad477dc0b 100644 --- a/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/src/main/resources/application.yml +++ b/test/plugin/scenarios/gateway-scenario/gateway-projectA-scenario/src/main/resources/application.yml @@ -33,4 +33,4 @@ spring: key-resolver: "#{@apiKeyResolver}" redis: host: 127.0.0.1 - port: 6379 \ No newline at end of file + port: 6379 diff --git a/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml b/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml index 9c29c6df9..e84b03b5a 100644 --- a/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml @@ -22,11 +22,7 @@ registryItems: - {webflux-projectB-scenario: 1} - {webflux-projectA-scenario: 1} operationNames: - - webflux-projectB-scenario: [org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.success, - org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.hello, - WEBFLUX.handle, org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.error, - org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.healthCheck, - RoutingConfiguration.org.apache.skywalking.apm.testcase.sc.webflux.projectB.route.TestHandler] + - webflux-projectB-scenario: [WEBFLUX.handle] - webflux-projectA-scenario: [/projectA/testcase] heartbeat: [] segmentItems: @@ -35,7 +31,7 @@ segmentItems: segments: - segmentId: not null spans: - - operationName: org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.success + - operationName: /testcase/annotation/success operationId: 0 parentSpanId: -1 spanId: 0 @@ -49,15 +45,17 @@ segmentItems: peer: '' peerId: 0 tags: - - {key: url, value: not null} + - {key: url, value: 'http://localhost:18080/testcase/annotation/success'} + - {key: http.method, value: GET} + - {key: status_code, value: '200'} refs: - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0, - entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null, - parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase, entryServiceInstanceId: not null} - segmentId: not null spans: - - operationName: org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.error + - operationName: /testcase/annotation/error operationId: 0 parentSpanId: -1 spanId: 0 @@ -71,22 +69,17 @@ segmentItems: peer: '' peerId: 0 tags: - - {key: url, value: not null} + - {key: url, value: 'http://localhost:18080/testcase/annotation/error'} + - {key: http.method, value: GET} - {key: status_code, value: '500'} - logs: - - logEvent: - - {key: event, value: error} - - {key: error.kind, value: java.lang.RuntimeException} - - {key: message, value: test_error} - - {key: stack, value: not null} refs: - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0, - entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null, - parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, + parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase, entryServiceInstanceId: not null} - segmentId: not null spans: - - operationName: RoutingConfiguration.org.apache.skywalking.apm.testcase.sc.webflux.projectB.route.TestHandler + - operationName: /testcase/annotation/{test} operationId: 0 parentSpanId: -1 spanId: 0 @@ -100,15 +93,65 @@ segmentItems: peer: '' peerId: 0 tags: - - {key: url, value: not null} + - {key: url, value: 'http://localhost:18080/testcase/annotation/foo'} + - {key: http.method, value: GET} + - {key: status_code, value: '200'} refs: - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0, - entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null, - parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 3, parentTraceSegmentId: not null, + parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase, entryServiceInstanceId: not null} - segmentId: not null spans: - - operationName: RoutingConfiguration.org.apache.skywalking.apm.testcase.sc.webflux.projectB.route.TestHandler + - operationName: /testcase/annotation/{test} + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 67 + componentName: '' + isError: false + spanType: Entry + peer: '' + peerId: 0 + tags: + - {key: url, value: 'http://localhost:18080/testcase/annotation/loo'} + - {key: http.method, value: GET} + - {key: status_code, value: '200'} + refs: + - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 4, parentTraceSegmentId: not null, + parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase, + entryServiceInstanceId: not null} + - segmentId: not null + spans: + - operationName: /testcase/route/{test} + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 67 + componentName: '' + isError: false + spanType: Entry + peer: '' + peerId: 0 + tags: + - {key: url, value: 'http://localhost:18080/testcase/route/success'} + - {key: http.method, value: GET} + - {key: status_code, value: '200'} + refs: + - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 5, parentTraceSegmentId: not null, + parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase, + entryServiceInstanceId: not null} + - segmentId: not null + spans: + - operationName: /testcase/route/{test} operationId: 0 parentSpanId: -1 spanId: 0 @@ -122,22 +165,17 @@ segmentItems: peer: '' peerId: 0 tags: - - {key: url, value: not null} + - {key: url, value: 'http://localhost:18080/testcase/route/error'} + - {key: http.method, value: GET} - {key: status_code, value: '500'} - logs: - - logEvent: - - {key: event, value: error} - - {key: error.kind, value: java.lang.RuntimeException} - - {key: message, value: test_error} - - {key: stack, value: not null} refs: - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0, - entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null, - parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 6, parentTraceSegmentId: not null, + parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase, entryServiceInstanceId: not null} - segmentId: not null spans: - - operationName: WEBFLUX.handle + - operationName: /** operationId: 0 parentSpanId: -1 spanId: 0 @@ -151,22 +189,17 @@ segmentItems: peer: '' peerId: 0 tags: - - {key: url, value: not null} + - {key: url, value: 'http://localhost:18080/notFound'} + - {key: http.method, value: GET} - {key: status_code, value: '404'} - logs: - - logEvent: - - {key: event, value: error} - - {key: error.kind, value: org.springframework.web.server.ResponseStatusException} - - {key: message, value: not null} - - {key: stack, value: not null} refs: - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0, - entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null, - parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 7, parentTraceSegmentId: not null, + parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase, entryServiceInstanceId: not null} - segmentId: not null spans: - - operationName: org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller.TestAnnotationController.hello + - operationName: /testcase/annotation/mono/hello operationId: 0 parentSpanId: -1 spanId: 0 @@ -180,11 +213,13 @@ segmentItems: peer: '' peerId: 0 tags: - - {key: url, value: not null} + - {key: url, value: 'http://localhost:18080/testcase/annotation/mono/hello'} + - {key: http.method, value: GET} + - {key: status_code, value: '200'} refs: - {parentEndpointId: 0, parentEndpoint: /projectA/testcase, networkAddressId: 0, - entryEndpointId: 0, refType: CrossProcess, parentSpanId: not null, parentTraceSegmentId: not null, - parentServiceInstanceId: not null, networkAddress: not null, entryEndpoint: /projectA/testcase, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 8, parentTraceSegmentId: not null, + parentServiceInstanceId: not null, networkAddress: 'localhost:18080', entryEndpoint: /projectA/testcase, entryServiceInstanceId: not null} - applicationCode: webflux-projectA-scenario segmentSize: nq 0 @@ -224,7 +259,7 @@ segmentItems: - {key: url, value: not null} - {key: http.method, value: GET} - {key: status_code, value: '500'} - - operationName: /testcase/route/success + - operationName: /testcase/annotation/foo operationId: 0 parentSpanId: 0 spanId: 3 @@ -235,6 +270,38 @@ segmentItems: componentName: '' isError: false spanType: Exit + peer: localhost:18080 + peerId: 0 + tags: + - {key: url, value: 'http://localhost:18080/testcase/annotation/foo'} + - {key: http.method, value: GET} + - operationName: /testcase/annotation/loo + operationId: 0 + parentSpanId: 0 + spanId: 4 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 2 + componentName: '' + isError: false + spanType: Exit + peer: localhost:18080 + peerId: 0 + tags: + - {key: url, value: 'http://localhost:18080/testcase/annotation/loo'} + - {key: http.method, value: GET} + - operationName: /testcase/route/success + operationId: 0 + parentSpanId: 0 + spanId: 5 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 2 + componentName: '' + isError: false + spanType: Exit peer: not null peerId: 0 tags: @@ -243,7 +310,7 @@ segmentItems: - operationName: /testcase/route/error operationId: 0 parentSpanId: 0 - spanId: 4 + spanId: 6 spanLayer: Http startTime: not null endTime: not null @@ -260,7 +327,7 @@ segmentItems: - operationName: /notFound operationId: 0 parentSpanId: 0 - spanId: 5 + spanId: 7 spanLayer: Http startTime: not null endTime: not null @@ -277,7 +344,7 @@ segmentItems: - operationName: /testcase/annotation/mono/hello operationId: 0 parentSpanId: 0 - spanId: 6 + spanId: 8 spanLayer: Http startTime: not null endTime: not null @@ -305,4 +372,4 @@ segmentItems: peerId: 0 tags: - {key: url, value: not null} - - {key: http.method, value: GET} \ No newline at end of file + - {key: http.method, value: GET} diff --git a/test/plugin/scenarios/webflux-scenario/configuration.yml b/test/plugin/scenarios/webflux-scenario/configuration.yml index 37b70f99e..8a507cd85 100644 --- a/test/plugin/scenarios/webflux-scenario/configuration.yml +++ b/test/plugin/scenarios/webflux-scenario/configuration.yml @@ -18,4 +18,6 @@ type: jvm entryService: http://localhost:8080/projectA/testcase healthCheck: http://localhost:8080/projectA/healthCheck startScript: ./bin/startup.sh -framework: spring-webflux \ No newline at end of file +framework: spring-webflux +runningMode: with_optional +withPlugins: apm-spring-webflux-5.x-plugin-*.jar diff --git a/test/plugin/scenarios/webflux-scenario/pom.xml b/test/plugin/scenarios/webflux-scenario/pom.xml index 8502b9871..dac1d5985 100644 --- a/test/plugin/scenarios/webflux-scenario/pom.xml +++ b/test/plugin/scenarios/webflux-scenario/pom.xml @@ -35,7 +35,7 @@ UTF-8 - 2.0.0.RELEASE + 2.1.1.RELEASE ${test.framework.version} diff --git a/test/plugin/scenarios/webflux-scenario/support-version.list b/test/plugin/scenarios/webflux-scenario/support-version.list index 13e43a550..553ef8e28 100644 --- a/test/plugin/scenarios/webflux-scenario/support-version.list +++ b/test/plugin/scenarios/webflux-scenario/support-version.list @@ -14,21 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -2.0.0.RELEASE -2.0.1.RELEASE -2.0.2.RELEASE -2.0.3.RELEASE -2.0.4.RELEASE -2.0.5.RELEASE -2.0.6.RELEASE -2.0.7.RELEASE -2.0.8.RELEASE -2.0.9.RELEASE -2.1.0.RELEASE +# 2.0.0-2.1.0 are supported, but due to the status code bug(https://github.com/spring-projects/spring-framework/issues/21901) +# we don’t test them 2.1.1.RELEASE 2.1.2.RELEASE 2.1.3.RELEASE 2.1.4.RELEASE 2.1.5.RELEASE 2.1.6.RELEASE -2.1.7.RELEASE \ No newline at end of file +2.1.7.RELEASE diff --git a/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml b/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml index 0d1389a28..b8fecfdb7 100644 --- a/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml +++ b/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml @@ -59,14 +59,4 @@ - - - spring-snapshots - http://repo.spring.io/snapshot - - - spring-milestones - http://repo.spring.io/milestone - - - \ No newline at end of file + diff --git a/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectA/controller/TestController.java b/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectA/controller/TestController.java index 85cbffcbe..eff3593ad 100644 --- a/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectA/controller/TestController.java +++ b/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectA/controller/TestController.java @@ -38,6 +38,8 @@ public class TestController { public String testcase() throws IOException { visit("http://" + hostBAddress + "/testcase/annotation/success"); visit("http://" + hostBAddress + "/testcase/annotation/error"); + visit("http://" + hostBAddress + "/testcase/annotation/foo"); + visit("http://" + hostBAddress + "/testcase/annotation/loo"); visit("http://" + hostBAddress + "/testcase/route/success"); visit("http://" + hostBAddress + "/testcase/route/error"); visit("http://" + hostBAddress + "/notFound"); diff --git a/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java b/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java index a9afbb5b4..2b45fe924 100644 --- a/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java +++ b/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/org/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java @@ -18,6 +18,7 @@ package org.apache.skywalking.apm.testcase.sc.webflux.projectB.controller; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -44,6 +45,11 @@ public class TestAnnotationController { return "1"; } + @GetMapping("/testcase/annotation/{test}") + public Mono urlPattern(@PathVariable("test") String var) { + return Mono.just(var); + } + @GetMapping("/testcase/annotation/mono/hello") public Mono hello(@RequestBody(required = false) String body) { return Mono.just("Hello World");