You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/09/27 14:38:32 UTC
[skywalking] branch master updated: add webflux webclient plugin
(#5493)
This is an automated email from the ASF dual-hosted git repository.
wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push:
new 806666b add webflux webclient plugin (#5493)
806666b is described below
commit 806666b4cc7df864d3f20796ec9a171151e72c0e
Author: vcjmhg <55...@users.noreply.github.com>
AuthorDate: Sun Sep 27 22:38:07 2020 +0800
add webflux webclient plugin (#5493)
---
.../network/trace/component/ComponentsDefine.java | 4 +-
apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml | 1 +
.../pom.xml | 38 +++----
.../webclient/BodyInserterRequestInterceptor.java | 54 ++++++++++
.../v5/webclient/WebFluxWebClientInterceptor.java | 116 +++++++++++++++++++++
.../define/BodyInserterRequestInstrumentation.java | 65 ++++++++++++
.../define/WebFluxWebClientInstrumentation.java | 72 +++++++++++++
.../src/main/resources/skywalking-plugin.def | 6 +-
.../setup/service-agent/java-agent/Plugin-list.md | 1 +
.../src/main/resources/component-libraries.yml | 3 +
test/e2e/e2e-protocol/src/main/proto | 2 +-
.../webflux-scenario/config/expectedData.yaml | 38 +++++++
.../webflux-scenario/support-version.list | 5 +-
.../webflux-projectA-scenario/pom.xml | 10 ++
.../projectA/controller/TestController.java | 19 +++-
.../controller/TestAnnotationController.java | 5 +
16 files changed, 406 insertions(+), 33 deletions(-)
diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
index 7bab86e..2494d1b 100755
--- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -178,4 +178,6 @@ public class ComponentsDefine {
public static final OfficialComponent QUARTZ_SCHEDULER = new OfficialComponent(97, "quartz-scheduler");
public static final OfficialComponent XXL_JOB = new OfficialComponent(98, "xxl-job");
-}
+
+ public static final OfficialComponent SPRING_WEBCLIENT = new OfficialComponent(99, "spring-webflux-webclient");
+}
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml
index 4887ce4..1444e7f 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml
@@ -40,6 +40,7 @@
<module>mvc-annotation-5.x-plugin</module>
<module>spring-kafka-2.x-plugin</module>
<module>scheduled-annotation-plugin</module>
+ <module>spring-webflux-5.x-webclient-plugin</module>
</modules>
<packaging>pom</packaging>
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml
similarity index 59%
copy from apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml
copy to apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml
index 4887ce4..076cfa0 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/pom.xml
@@ -18,37 +18,27 @@
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
<parent>
+ <artifactId>spring-plugins</artifactId>
<groupId>org.apache.skywalking</groupId>
- <artifactId>apm-sdk-plugin</artifactId>
<version>8.2.0-SNAPSHOT</version>
</parent>
+ <modelVersion>4.0.0</modelVersion>
- <artifactId>spring-plugins</artifactId>
- <modules>
- <module>async-annotation-plugin</module>
- <module>concurrent-util-4.x-plugin</module>
- <module>resttemplate-4.x-plugin</module>
- <module>mvc-annotation-4.x-plugin</module>
- <module>spring-cloud</module>
- <module>mvc-annotation-3.x-plugin</module>
- <module>core-patch</module>
- <module>mvc-annotation-commons</module>
- <module>spring-commons</module>
- <module>mvc-annotation-5.x-plugin</module>
- <module>spring-kafka-2.x-plugin</module>
- <module>scheduled-annotation-plugin</module>
- </modules>
- <packaging>pom</packaging>
+ <artifactId>spring-webflux-5.x-webclient-plugin</artifactId>
- <name>apm-sdk-plugin</name>
<url>http://maven.apache.org</url>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webflux</artifactId>
+ <version>5.0.0.RELEASE</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
<properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <sdk.plugin.related.dir>/..</sdk.plugin.related.dir>
+ <compiler.version>1.8</compiler.version>
</properties>
-
-</project>
+</project>
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/BodyInserterRequestInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/BodyInserterRequestInterceptor.java
new file mode 100644
index 0000000..f65d7c0
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/BodyInserterRequestInterceptor.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.webflux.v5.webclient;
+
+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.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.client.reactive.ClientHttpRequest;
+
+import java.lang.reflect.Method;
+
+public class BodyInserterRequestInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ ClientHttpRequest clientHttpRequest = (ClientHttpRequest) allArguments[0];
+ ContextCarrier contextCarrier = (ContextCarrier) objInst.getSkyWalkingDynamicField();
+ CarrierItem next = contextCarrier.items();
+ while (next.hasNext()) {
+ next = next.next();
+ clientHttpRequest.getHeaders().set(next.getHeadKey(), next.getHeadValue());
+ }
+ }
+
+ @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/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/WebFluxWebClientInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/WebFluxWebClientInterceptor.java
new file mode 100644
index 0000000..1674c48
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/WebFluxWebClientInterceptor.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 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.webclient;
+
+import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.reactive.function.client.ClientRequest;
+import org.springframework.web.reactive.function.client.ClientResponse;
+import reactor.core.publisher.Mono;
+
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.function.BiConsumer;
+
+public class WebFluxWebClientInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+ if (allArguments[0] == null) {
+ //illegal args,can't trace ignore
+ return;
+ }
+
+ ClientRequest request = (ClientRequest) allArguments[0];
+ final ContextCarrier contextCarrier = new ContextCarrier();
+
+ URI uri = request.url();
+ final String requestURIString = getRequestURIString(uri);
+ final String operationName = requestURIString;
+ final String remotePeer = getIPAndPort(uri);
+ AbstractSpan span = ContextManager.createExitSpan(operationName, contextCarrier, remotePeer);
+
+ //set componet name
+ span.setComponent(ComponentsDefine.SPRING_WEBCLIENT);
+ Tags.URL.set(span, uri.toString());
+ Tags.HTTP.METHOD.set(span, request.method().toString());
+ SpanLayer.asHttp(span);
+
+ if (request instanceof EnhancedInstance) {
+ ((EnhancedInstance) request).setSkyWalkingDynamicField(contextCarrier);
+ }
+
+ //user async interface
+ span.prepareForAsync();
+ ContextManager.stopSpan();
+
+ objInst.setSkyWalkingDynamicField(span);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+ // fix the problem that allArgument[0] may be null
+ if (allArguments[0] == null) {
+ return ret;
+ }
+ Mono<ClientResponse> ret1 = (Mono<ClientResponse>) ret;
+ AbstractSpan span = (AbstractSpan) objInst.getSkyWalkingDynamicField();
+ return ret1.doAfterSuccessOrError(new BiConsumer<ClientResponse, Throwable>() {
+ @Override
+ public void accept(ClientResponse clientResponse, Throwable throwable) {
+ HttpStatus httpStatus = clientResponse.statusCode();
+ if (httpStatus != null) {
+ Tags.STATUS_CODE.set(span, Integer.toString(httpStatus.value()));
+ if (httpStatus.isError()) {
+ span.errorOccurred();
+ }
+ }
+ }
+ }).doOnError(error -> {
+ span.log(error);
+ }).doFinally(s -> {
+ span.asyncFinish();
+ });
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+ AbstractSpan activeSpan = ContextManager.activeSpan();
+ activeSpan.errorOccurred();
+ activeSpan.log(t);
+ }
+
+ private String getRequestURIString(URI uri) {
+ String requestPath = uri.getPath();
+ return requestPath != null && requestPath.length() > 0 ? requestPath : "/";
+ }
+
+ // return ip:port
+ private String getIPAndPort(URI uri) {
+ return uri.getHost() + ":" + uri.getPort();
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/define/BodyInserterRequestInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/define/BodyInserterRequestInstrumentation.java
new file mode 100644
index 0000000..e58be98
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/define/BodyInserterRequestInstrumentation.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.spring.webflux.v5.webclient.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+public class BodyInserterRequestInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription> getMethodsMatcher() {
+ return named("writeTo").and(takesArgumentWithType(0, "org.springframework.http.client.reactive.ClientHttpRequest"));
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return "org.apache.skywalking.apm.plugin.spring.webflux.v5.webclient.BodyInserterRequestInterceptor";
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return byName("org.springframework.web.reactive.function.client.DefaultClientRequestBuilder$BodyInserterRequest");
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/define/WebFluxWebClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/define/WebFluxWebClientInstrumentation.java
new file mode 100644
index 0000000..1b2652e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/webflux/v5/webclient/define/WebFluxWebClientInstrumentation.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.spring.webflux.v5.webclient.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+
+public class WebFluxWebClientInstrumentation extends ClassEnhancePluginDefine {
+ private static final String ENHANCE_CLASS = "org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction";
+ private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.spring.webflux.v5.webclient.WebFluxWebClientInterceptor";
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return NameMatch.byName(ENHANCE_CLASS);
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[]{
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription> getMethodsMatcher() {
+ return named("exchange");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return INTERCEPT_CLASS;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
+ return new StaticMethodsInterceptPoint[0];
+ }
+}
\ No newline at end of file
diff --git a/test/plugin/scenarios/webflux-scenario/support-version.list b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/resources/skywalking-plugin.def
similarity index 75%
copy from test/plugin/scenarios/webflux-scenario/support-version.list
copy to apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/resources/skywalking-plugin.def
index c5820da..260ce00 100644
--- a/test/plugin/scenarios/webflux-scenario/support-version.list
+++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/spring-webflux-5.x-webclient-plugin/src/main/resources/skywalking-plugin.def
@@ -14,7 +14,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# 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.7.RELEASE
+spring-webflux-5.x-webclient=org.apache.skywalking.apm.plugin.spring.webflux.v5.webclient.define.BodyInserterRequestInstrumentation
+spring-webflux-5.x-webclient=org.apache.skywalking.apm.plugin.spring.webflux.v5.webclient.define.WebFluxWebClientInstrumentation
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 4d4c9fc..79a1410 100644
--- a/docs/en/setup/service-agent/java-agent/Plugin-list.md
+++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md
@@ -87,6 +87,7 @@
- spring-scheduled-annotation
- spring-tx
- spring-webflux-5.x
+- spring-webflux-5.x-webclient
- spymemcached-2.x
- struts2-2.x
- tomcat-7.x/8.x
diff --git a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml
index b12d93d..d86fe6d 100755
--- a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml
+++ b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml
@@ -326,6 +326,9 @@ quartz-scheduler:
xxl-job:
id: 98
languages: Java
+spring-webflux-webclient:
+ id: 99
+ languages: Java
# .NET/.NET Core components
# [3000, 4000) for C#/.NET only
diff --git a/test/e2e/e2e-protocol/src/main/proto b/test/e2e/e2e-protocol/src/main/proto
index b2f381e..9933e2d 160000
--- a/test/e2e/e2e-protocol/src/main/proto
+++ b/test/e2e/e2e-protocol/src/main/proto
@@ -1 +1 @@
-Subproject commit b2f381e63702bc43216ef5576637195102302c6e
+Subproject commit 9933e2d17078c2bf07cd1c8d5ef36d52b5cbb917
diff --git a/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml b/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml
index f96d6ff..d6c62c7 100644
--- a/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/webflux-scenario/config/expectedData.yaml
@@ -193,6 +193,28 @@ segmentItems:
parentSpanId: 8, parentTraceSegmentId: not null, parentServiceInstance: not
null, parentService: not null, traceId: not null}
skipAnalysis: 'false'
+ - segmentId: not null
+ spans:
+ - operationName: /testcase/webclient/server
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: not null
+ endTime: not null
+ componentId: 67
+ isError: false
+ spanType: Entry
+ peer: ''
+ tags:
+ - {key: url, value: 'http://localhost:18080/testcase/webclient/server'}
+ - {key: http.method, value: GET}
+ - {key: status_code, value: '200'}
+ refs:
+ - {parentEndpoint: /projectA/testcase, networkAddress: 'localhost:18080', refType: CrossProcess,
+ parentSpanId: 9, parentTraceSegmentId: not null, parentServiceInstance: not
+ null, parentService: not null, traceId: not null}
+ skipAnalysis: 'false'
- serviceName: webflux-projectA-scenario
segmentSize: nq 0
segments:
@@ -321,6 +343,22 @@ segmentItems:
- {key: url, value: not null}
- {key: http.method, value: GET}
skipAnalysis: 'false'
+ - operationName: /testcase/webclient/server
+ operationId: 0
+ parentSpanId: 0
+ spanId: 9
+ spanLayer: Http
+ startTime: not null
+ endTime: not null
+ componentId: 99
+ isError: false
+ spanType: Exit
+ peer: not null
+ tags:
+ - {key: url, value: not null}
+ - {key: http.method, value: GET}
+ - {key: status_code, value:'200'}
+ skipAnalysis: 'false'
- operationName: /projectA/testcase
operationId: 0
parentSpanId: -1
diff --git a/test/plugin/scenarios/webflux-scenario/support-version.list b/test/plugin/scenarios/webflux-scenario/support-version.list
index c5820da..ea20445 100644
--- a/test/plugin/scenarios/webflux-scenario/support-version.list
+++ b/test/plugin/scenarios/webflux-scenario/support-version.list
@@ -16,5 +16,6 @@
# 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.7.RELEASE
+2.1.17.RELEASE
+2.2.10.RELEASE
+2.3.4.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 b8fecfd..966af80 100644
--- a/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml
+++ b/test/plugin/scenarios/webflux-scenario/webflux-projectA-scenario/pom.xml
@@ -39,6 +39,16 @@
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webflux</artifactId>
+ <version>5.2.9.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-reactor-netty</artifactId>
+ <version>2.3.4.RELEASE</version>
+ </dependency>
</dependencies>
<build>
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 4205145..b11f743 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
@@ -17,12 +17,15 @@
package org.apache.skywalking.apm.testcase.sc.webflux.projectA.controller;
-import java.io.IOException;
import org.apache.skywalking.apm.testcase.sc.webflux.projectA.utils.HttpUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Mono;
+
+import java.io.IOException;
@RestController
public class TestController {
@@ -43,6 +46,7 @@ public class TestController {
visit("http://" + hostBAddress + "/testcase/route/error");
visit("http://" + hostBAddress + "/notFound");
visit("http://" + hostBAddress + "/testcase/annotation/mono/hello");
+ testGet("http://" + hostBAddress + "/testcase/webclient/server");
return "test";
}
@@ -59,4 +63,17 @@ public class TestController {
}
}
+
+ /**
+ * test webflux webclient plugin
+ */
+ private void testGet(String remoteUri) {
+ Mono<String> response = WebClient
+ .create()
+ .get()
+ .uri(remoteUri)
+ .retrieve()
+ .bodyToMono(String.class);
+ response.subscribe();
+ }
}
diff --git a/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java b/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java
index dfd121f..293dc90 100644
--- a/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java
+++ b/test/plugin/scenarios/webflux-scenario/webflux-projectB-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/webflux/projectB/controller/TestAnnotationController.java
@@ -44,6 +44,11 @@ public class TestAnnotationController {
}
return "1";
}
+
+ @RequestMapping("/testcase/webclient/server")
+ public String webclientServer(){
+ return "success";
+ }
@GetMapping("/testcase/annotation/{test}")
public Mono<String> urlPattern(@PathVariable("test") String var) {