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 b732ff3 Fix ClassCast issue for RequestHolder/ResponseHolder (#6973)
b732ff3 is described below
commit b732ff35a7fd0d99ef1e5f4b9a66170fa812f6cd
Author: Lu Jiajing <[email protected]>
AuthorDate: Sat May 22 17:06:13 2021 +0800
Fix ClassCast issue for RequestHolder/ResponseHolder (#6973)
---
.github/workflows/plugins-test.0.yaml | 1 +
CHANGES.md | 1 +
.../core/context/ContextManagerBenchmark.java | 97 +++++++++++
.../mvc/v3/HandlerMethodInvokerInterceptor.java | 5 +-
.../plugin/spring/mvc/v4/SpringTestCaseHelper.java | 6 +-
.../plugin/spring/mvc/v5/GetBeanInterceptor.java | 6 +-
.../plugin/spring/mvc/v5/InvokeInterceptor.java | 62 +++----
.../v5/define/AbstractSpring5Instrumentation.java | 4 +-
.../AbstractSpring5ReactiveInstrumentation.java | 4 +-
... AbstractSpring5ReactiveInstrumentationV2.java} | 8 +-
.../InvocableHandlerMethodInstrumentation.java | 13 +-
.../apm/plugin/spring/mvc/commons/Constants.java | 2 +
.../mvc/commons/JavaxServletRequestHolder.java | 56 -------
.../spring/mvc/commons/ReactiveRequestHolder.java | 66 --------
.../spring/mvc/commons/ReactiveResponseHolder.java | 45 -----
.../apm/plugin/spring/mvc/commons/RequestUtil.java | 110 ++++++++++++
.../plugin/spring/mvc/commons/ResponseHolder.java | 22 ---
.../interceptor/AbstractMethodInterceptor.java | 186 +++++++++++----------
.../commons/interceptor/GetBeanInterceptor.java | 5 +-
.../interceptor/InvokeForRequestInterceptor.java | 5 +-
.../InvokeHandlerMethodInterceptor.java | 13 +-
.../bin/startup.sh | 24 +++
.../config/expectedData.yaml | 103 ++++++++++++
.../configuration.yml | 20 +++
.../pom.xml | 35 +++-
.../src/main/assembly/assembly.xml | 49 ++++++
.../testcase/sc/springmvcreactive/Application.java | 20 +--
.../springmvcreactive/controller/Controller.java | 60 +++++++
.../sc/springmvcreactive/service/TestService.java | 25 ++-
.../src/main/resources/application.yml | 18 ++
.../support-version.list | 20 +++
.../scenarios/springmvc-reactive-scenario/pom.xml | 2 +-
32 files changed, 719 insertions(+), 374 deletions(-)
diff --git a/.github/workflows/plugins-test.0.yaml
b/.github/workflows/plugins-test.0.yaml
index b627277..43cf875 100644
--- a/.github/workflows/plugins-test.0.yaml
+++ b/.github/workflows/plugins-test.0.yaml
@@ -69,6 +69,7 @@ jobs:
- gson-scenario
- elasticjob-3.x-scenario
- springmvc-reactive-scenario
+ - springmvc-reactive-devtools-scenario
steps:
- uses: actions/checkout@v2
with:
diff --git a/CHANGES.md b/CHANGES.md
index 36d3685..7eb1499 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -30,6 +30,7 @@ Release Notes.
* Fix the conversion problem of float type in ConfigInitializer.
* Fixed part of the dynamic configuration of ConfigurationDiscoveryService
that does not take effect under certain circumstances.
* Introduce method interceptor API v2
+* Fix ClassCast issue for RequestHolder/ResponseHolder.
#### OAP-Backend
* BugFix: filter invalid Envoy access logs whose socket address is empty.
diff --git
a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/ContextManagerBenchmark.java
b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/ContextManagerBenchmark.java
new file mode 100644
index 0000000..8810129
--- /dev/null
+++
b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/context/ContextManagerBenchmark.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.agent.core.context;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.profile.GCProfiler;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class ContextManagerBenchmark {
+ @Benchmark
+ @Fork(value = 1, warmups = 1)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.SampleTime)
+ public void getKeyFromThreadLocal(Blackhole bh) {
+ bh.consume(ContextManager.getRuntimeContext().get("KEY"));
+ }
+
+ @Benchmark
+ @Fork(value = 1, warmups = 1)
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.SampleTime)
+ public void isAssignableFrom(Blackhole bh) {
+ bh.consume(Map.class.isAssignableFrom(HashMap.class));
+ }
+
+ public static void main(String[] args) throws Exception {
+ Options opt = new
OptionsBuilder().include(ContextManagerBenchmark.class.getSimpleName())
+ .addProfiler(GCProfiler.class)
+ .build();
+ new Runner(opt).run();
+ }
+
+ /**
+ * # JMH version: 1.21
+ * # VM version: JDK 1.8.0_292, OpenJDK 64-Bit Server VM, 25.292-b10
+ * # VM invoker:
/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/jre/bin/java
+ * # VM options: -javaagent:/Applications/IntelliJ
IDEA.app/Contents/lib/idea_rt.jar=62459:/Applications/IntelliJ
IDEA.app/Contents/bin -Dfile.encoding=UTF-8
+ * # Warmup: 5 iterations, 10 s each
+ * # Measurement: 5 iterations, 10 s each
+ * # Timeout: 10 min per iteration
+ * # Threads: 1 thread, will synchronize iterations
+ * # Benchmark mode: Sampling time
+ *
+ * Benchmark
Mode Cnt Score Error Units
+ * ContextManagerBenchmark.getKeyFromThreadLocal
sample 1332415 48.066 ± 0.765 ns/op
+ *
ContextManagerBenchmark.getKeyFromThreadLocal:getKeyFromThreadLocal·p0.00
sample 11.000 ns/op
+ *
ContextManagerBenchmark.getKeyFromThreadLocal:getKeyFromThreadLocal·p0.50
sample 42.000 ns/op
+ *
ContextManagerBenchmark.getKeyFromThreadLocal:getKeyFromThreadLocal·p0.90
sample 45.000 ns/op
+ *
ContextManagerBenchmark.getKeyFromThreadLocal:getKeyFromThreadLocal·p0.95
sample 47.000 ns/op
+ *
ContextManagerBenchmark.getKeyFromThreadLocal:getKeyFromThreadLocal·p0.99
sample 93.000 ns/op
+ *
ContextManagerBenchmark.getKeyFromThreadLocal:getKeyFromThreadLocal·p0.999
sample 652.000 ns/op
+ *
ContextManagerBenchmark.getKeyFromThreadLocal:getKeyFromThreadLocal·p0.9999
sample 11236.403 ns/op
+ *
ContextManagerBenchmark.getKeyFromThreadLocal:getKeyFromThreadLocal·p1.00
sample 144384.000 ns/op
+ * ContextManagerBenchmark.getKeyFromThreadLocal:·gc.alloc.rate
sample 5 0.022 ± 0.010 MB/sec
+ * ContextManagerBenchmark.getKeyFromThreadLocal:·gc.alloc.rate.norm
sample 5 ≈ 10⁻⁴ B/op
+ * ContextManagerBenchmark.getKeyFromThreadLocal:·gc.count
sample 5 ≈ 0 counts
+ * ContextManagerBenchmark.isAssignableFrom
sample 1182629 45.894 ± 0.939 ns/op
+ * ContextManagerBenchmark.isAssignableFrom:isAssignableFrom·p0.00
sample 7.000 ns/op
+ * ContextManagerBenchmark.isAssignableFrom:isAssignableFrom·p0.50
sample 39.000 ns/op
+ * ContextManagerBenchmark.isAssignableFrom:isAssignableFrom·p0.90
sample 43.000 ns/op
+ * ContextManagerBenchmark.isAssignableFrom:isAssignableFrom·p0.95
sample 46.000 ns/op
+ * ContextManagerBenchmark.isAssignableFrom:isAssignableFrom·p0.99
sample 89.000 ns/op
+ * ContextManagerBenchmark.isAssignableFrom:isAssignableFrom·p0.999
sample 606.000 ns/op
+ * ContextManagerBenchmark.isAssignableFrom:isAssignableFrom·p0.9999
sample 15904.000 ns/op
+ * ContextManagerBenchmark.isAssignableFrom:isAssignableFrom·p1.00
sample 138240.000 ns/op
+ * ContextManagerBenchmark.isAssignableFrom:·gc.alloc.rate
sample 5 0.021 ± 0.007 MB/sec
+ * ContextManagerBenchmark.isAssignableFrom:·gc.alloc.rate.norm
sample 5 ≈ 10⁻⁴ B/op
+ * ContextManagerBenchmark.isAssignableFrom:·gc.count
sample 5 ≈ 0 counts
+ */
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v3/HandlerMethodInvokerInterceptor.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v3/HandlerMethodInvokerInterceptor.java
index dd60587..2123338 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v3/HandlerMethodInvokerInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v3/HandlerMethodInvokerInterceptor.java
@@ -19,12 +19,10 @@
package org.apache.skywalking.apm.plugin.spring.mvc.v3;
import java.lang.reflect.Method;
-import javax.servlet.http.HttpServletResponse;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.JavaxServletResponseHolder;
import org.springframework.web.context.request.NativeWebRequest;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.RESPONSE_KEY_IN_RUNTIME_CONTEXT;
@@ -40,8 +38,7 @@ public class HandlerMethodInvokerInterceptor implements
InstanceMethodsAroundInt
Object handler = allArguments[1];
if (handler instanceof EnhancedInstance) {
ContextManager.getRuntimeContext()
- .put(RESPONSE_KEY_IN_RUNTIME_CONTEXT, new
JavaxServletResponseHolder(
- (HttpServletResponse) ((NativeWebRequest)
allArguments[2]).getNativeResponse()));
+ .put(RESPONSE_KEY_IN_RUNTIME_CONTEXT,
((NativeWebRequest) allArguments[2]).getNativeResponse());
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/SpringTestCaseHelper.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/SpringTestCaseHelper.java
index 2447d20..ffcee2a 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/SpringTestCaseHelper.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/spring/mvc/v4/SpringTestCaseHelper.java
@@ -22,16 +22,14 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.JavaxServletRequestHolder;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.JavaxServletResponseHolder;
public final class SpringTestCaseHelper {
public final static void createCaseHandler(HttpServletRequest request,
HttpServletResponse response,
CaseHandler a) throws Throwable {
ContextManager.createLocalSpan("For-Test");
-
ContextManager.getRuntimeContext().put(Constants.REQUEST_KEY_IN_RUNTIME_CONTEXT,
new JavaxServletRequestHolder(request));
-
ContextManager.getRuntimeContext().put(Constants.RESPONSE_KEY_IN_RUNTIME_CONTEXT,
new JavaxServletResponseHolder(response));
+
ContextManager.getRuntimeContext().put(Constants.REQUEST_KEY_IN_RUNTIME_CONTEXT,
request);
+
ContextManager.getRuntimeContext().put(Constants.RESPONSE_KEY_IN_RUNTIME_CONTEXT,
response);
a.handleCase();
ContextManager.stopSpan();
ContextManager.getRuntimeContext().remove(Constants.CONTROLLER_METHOD_STACK_DEPTH);
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/GetBeanInterceptor.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/GetBeanInterceptor.java
index b2014c7..b063656 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/GetBeanInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/GetBeanInterceptor.java
@@ -22,8 +22,6 @@ import
org.apache.skywalking.apm.agent.core.context.ContextManager;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.JavaxServletRequestHolder;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.JavaxServletResponseHolder;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@@ -50,12 +48,12 @@ public class GetBeanInterceptor implements
InstanceMethodsAroundInterceptor {
ContextManager.getRuntimeContext()
.put(
REQUEST_KEY_IN_RUNTIME_CONTEXT,
- new
JavaxServletRequestHolder(requestAttributes.getRequest())
+ requestAttributes.getRequest()
);
ContextManager.getRuntimeContext()
.put(
RESPONSE_KEY_IN_RUNTIME_CONTEXT,
- new
JavaxServletResponseHolder(requestAttributes.getResponse())
+ requestAttributes.getResponse()
);
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/InvokeInterceptor.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/InvokeInterceptor.java
index 0b13d2d..50eb1ea 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/InvokeInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/InvokeInterceptor.java
@@ -17,48 +17,56 @@
package org.apache.skywalking.apm.plugin.spring.mvc.v5;
-import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.RuntimeContext;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
-import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.ReactiveRequestHolder;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.ReactiveResponseHolder;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
+import java.lang.reflect.Method;
+
+import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.REACTIVE_ASYNC_SPAN_IN_RUNTIME_CONTEXT;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.REQUEST_KEY_IN_RUNTIME_CONTEXT;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.RESPONSE_KEY_IN_RUNTIME_CONTEXT;
-public class InvokeInterceptor implements InstanceMethodsAroundInterceptor {
+public class InvokeInterceptor implements InstanceMethodsAroundInterceptorV2 {
@Override
- public void beforeMethod(final EnhancedInstance objInst,
- final Method method,
- final Object[] allArguments,
- final Class<?>[] argumentsTypes,
- final MethodInterceptResult result) throws
Throwable {
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes, MethodInvocationContext context)
throws Throwable {
ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
- final ReactiveResponseHolder responseHolder = new
ReactiveResponseHolder(exchange.getResponse());
- ContextManager.getRuntimeContext()
- .put(RESPONSE_KEY_IN_RUNTIME_CONTEXT, responseHolder);
- ContextManager.getRuntimeContext()
- .put(REQUEST_KEY_IN_RUNTIME_CONTEXT, new
ReactiveRequestHolder(exchange.getRequest()));
- objInst.setSkyWalkingDynamicField(responseHolder);
+ final ServerHttpResponse response = exchange.getResponse();
+ /**
+ * First, we put the slot in the RuntimeContext,
+ * as well as the MethodInvocationContext (MIC),
+ * so that we can access it in the {@link
org.apache.skywalking.apm.plugin.spring.mvc.v5.InvokeInterceptor#afterMethod}
+ * Then we fetch the slot from {@link
org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor.AbstractMethodInterceptor#afterMethod}
+ * and fulfill the slot with the real AbstractSpan.
+ * Afterwards, we can safely remove the RuntimeContext.
+ * Finally, when the lambda executes in the {@link
reactor.core.publisher.Mono#doFinally},
+ * ref of span could be acquired from MIC.
+ */
+ AbstractSpan[] ref = new AbstractSpan[1];
+ RuntimeContext runtimeContext = ContextManager.getRuntimeContext();
+ runtimeContext.put(REACTIVE_ASYNC_SPAN_IN_RUNTIME_CONTEXT, ref);
+ runtimeContext.put(RESPONSE_KEY_IN_RUNTIME_CONTEXT, response);
+ runtimeContext.put(REQUEST_KEY_IN_RUNTIME_CONTEXT,
exchange.getRequest());
+ context.setContext(ref);
}
@Override
- public Object afterMethod(final EnhancedInstance objInst,
- final Method method,
- final Object[] allArguments,
- final Class<?>[] argumentsTypes,
- final Object ret) throws Throwable {
+ public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Object ret,
MethodInvocationContext context) throws Throwable {
ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
return ((Mono) ret).doFinally(s -> {
- ReactiveResponseHolder responseHolder = (ReactiveResponseHolder)
objInst.getSkyWalkingDynamicField();
- AbstractSpan span = responseHolder.getSpan();
+ Object ctx = context.getContext();
+ if (ctx == null) {
+ return;
+ }
+ AbstractSpan span = ((AbstractSpan[]) ctx)[0];
if (span == null) {
return;
}
@@ -72,11 +80,7 @@ public class InvokeInterceptor implements
InstanceMethodsAroundInterceptor {
}
@Override
- public void handleMethodException(final EnhancedInstance objInst,
- final Method method,
- final Object[] allArguments,
- final Class<?>[] argumentsTypes,
- final Throwable t) {
+ public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Throwable t,
MethodInvocationContext context) {
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/AbstractSpring5Instrumentation.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/AbstractSpring5Instrumentation.java
index 1f1ee13..28d4de3 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/AbstractSpring5Instrumentation.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/AbstractSpring5Instrumentation.java
@@ -20,10 +20,10 @@ package
org.apache.skywalking.apm.plugin.spring.mvc.v5.define;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
public abstract class AbstractSpring5Instrumentation extends
ClassInstanceMethodsEnhancePluginDefine {
- public static final String WITHNESS_CLASSES =
"org.springframework.web.servlet.resource.HttpResource";
+ public static final String WITNESS_CLASSES =
"org.springframework.web.servlet.resource.HttpResource";
@Override
protected final String[] witnessClasses() {
- return new String[] {WITHNESS_CLASSES};
+ return new String[] {WITNESS_CLASSES};
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentation.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentation.java
index 8d37b84..5753deb 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentation.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentation.java
@@ -20,10 +20,10 @@ package
org.apache.skywalking.apm.plugin.spring.mvc.v5.define.reactive;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
public abstract class AbstractSpring5ReactiveInstrumentation extends
ClassInstanceMethodsEnhancePluginDefine {
- public static final String WITHNESS_CLASSES =
"org.springframework.web.reactive.result.method.InvocableHandlerMethod";
+ public static final String WITNESS_CLASSES =
"org.springframework.web.reactive.result.method.InvocableHandlerMethod";
@Override
protected final String[] witnessClasses() {
- return new String[] {WITHNESS_CLASSES};
+ return new String[] {WITNESS_CLASSES};
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentation.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentationV2.java
similarity index 75%
copy from
apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentation.java
copy to
apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentationV2.java
index 8d37b84..52adbb7 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentation.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/AbstractSpring5ReactiveInstrumentationV2.java
@@ -17,13 +17,13 @@
package org.apache.skywalking.apm.plugin.spring.mvc.v5.define.reactive;
-import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2;
-public abstract class AbstractSpring5ReactiveInstrumentation extends
ClassInstanceMethodsEnhancePluginDefine {
- public static final String WITHNESS_CLASSES =
"org.springframework.web.reactive.result.method.InvocableHandlerMethod";
+public abstract class AbstractSpring5ReactiveInstrumentationV2 extends
ClassInstanceMethodsEnhancePluginDefineV2 {
+ public static final String WITNESS_CLASSES =
"org.springframework.web.reactive.result.method.InvocableHandlerMethod";
@Override
protected final String[] witnessClasses() {
- return new String[] {WITHNESS_CLASSES};
+ return new String[] {WITNESS_CLASSES};
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/InvocableHandlerMethodInstrumentation.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/InvocableHandlerMethodInstrumentation.java
index 27884ed..b0a8bdb 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/InvocableHandlerMethodInstrumentation.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/v5/define/reactive/InvocableHandlerMethodInstrumentation.java
@@ -20,15 +20,14 @@ package
org.apache.skywalking.apm.plugin.spring.mvc.v5.define.reactive;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
-import
org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
-import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static
org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
import static
org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
-public class InvocableHandlerMethodInstrumentation extends
ClassInstanceMethodsEnhancePluginDefine {
+public class InvocableHandlerMethodInstrumentation extends
AbstractSpring5ReactiveInstrumentationV2 {
@Override
protected ClassMatch enhanceClass() {
return
byName("org.springframework.web.reactive.result.method.InvocableHandlerMethod");
@@ -40,9 +39,9 @@ public class InvocableHandlerMethodInstrumentation extends
ClassInstanceMethodsE
}
@Override
- public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints()
{
- return new InstanceMethodsInterceptPoint[] {
- new InstanceMethodsInterceptPoint() {
+ public InstanceMethodsInterceptV2Point[]
getInstanceMethodsInterceptV2Points() {
+ return new InstanceMethodsInterceptV2Point[] {
+ new InstanceMethodsInterceptV2Point() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named("invoke").and(
@@ -50,7 +49,7 @@ public class InvocableHandlerMethodInstrumentation extends
ClassInstanceMethodsE
}
@Override
- public String getMethodsInterceptor() {
+ public String getMethodsInterceptorV2() {
return
"org.apache.skywalking.apm.plugin.spring.mvc.v5.InvokeInterceptor";
}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/Constants.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/Constants.java
index 6341b06..85a389f 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/Constants.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/Constants.java
@@ -34,6 +34,8 @@ public class Constants {
public static final String RESPONSE_KEY_IN_RUNTIME_CONTEXT = "SW_RESPONSE";
+ public static final String REACTIVE_ASYNC_SPAN_IN_RUNTIME_CONTEXT =
"SW_REACTIVE_RESPONSE_ASYNC_SPAN";
+
public static final String FORWARD_REQUEST_FLAG =
"SW_FORWARD_REQUEST_FLAG";
public static final String WEBFLUX_REQUEST_KEY = "SW_WEBFLUX_REQUEST_KEY";
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/JavaxServletRequestHolder.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/JavaxServletRequestHolder.java
deleted file mode 100644
index 8eb5705..0000000
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/JavaxServletRequestHolder.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.skywalking.apm.plugin.spring.mvc.commons;
-
-import java.util.Enumeration;
-import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-
-public class JavaxServletRequestHolder implements RequestHolder {
-
- private final HttpServletRequest request;
-
- public JavaxServletRequestHolder(HttpServletRequest request) {
- this.request = request;
- }
-
- @Override
- public String getHeader(final String headerName) {
- return request.getHeader(headerName);
- }
-
- @Override
- public Enumeration<String> getHeaders(final String headerName) {
- return request.getHeaders(headerName);
- }
-
- @Override
- public String requestURL() {
- return request.getRequestURL().toString();
- }
-
- @Override
- public String requestMethod() {
- return request.getMethod();
- }
-
- @Override
- public Map<String, String[]> getParameterMap() {
- return request.getParameterMap();
- }
-}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveRequestHolder.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveRequestHolder.java
deleted file mode 100644
index b5e1876..0000000
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveRequestHolder.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.skywalking.apm.plugin.spring.mvc.commons;
-
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.springframework.http.server.reactive.ServerHttpRequest;
-
-public class ReactiveRequestHolder implements RequestHolder {
- private final ServerHttpRequest serverHttpRequest;
-
- public ReactiveRequestHolder(final ServerHttpRequest serverHttpRequest) {
- this.serverHttpRequest = serverHttpRequest;
- }
-
- @Override
- public String getHeader(final String headerName) {
- return this.serverHttpRequest.getHeaders().getFirst(headerName);
- }
-
- @Override
- public Enumeration<String> getHeaders(final String headerName) {
- List<String> values =
this.serverHttpRequest.getHeaders().get(headerName);
- if (values == null) {
- return Collections.enumeration(Collections.EMPTY_LIST);
- }
- return Collections.enumeration(values);
- }
-
- @Override
- public String requestURL() {
- return this.serverHttpRequest.getURI().toString();
- }
-
- @Override
- public String requestMethod() {
- return this.serverHttpRequest.getMethodValue();
- }
-
- @Override
- public Map<String, String[]> getParameterMap() {
- Map<String, String[]> parameterMap = new
HashMap<>(this.serverHttpRequest.getQueryParams().size());
- this.serverHttpRequest.getQueryParams().forEach((key, value) -> {
- parameterMap.put(key, value.toArray(new String[0]));
- });
- return parameterMap;
- }
-}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveResponseHolder.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveResponseHolder.java
deleted file mode 100644
index 995114c..0000000
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ReactiveResponseHolder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.skywalking.apm.plugin.spring.mvc.commons;
-
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
-import org.springframework.http.server.reactive.ServerHttpResponse;
-
-public class ReactiveResponseHolder implements ResponseHolder {
-
- private final ServerHttpResponse response;
-
- private AbstractSpan span;
-
- public ReactiveResponseHolder(final ServerHttpResponse response) {
- this.response = response;
- }
-
- public void setSpan(AbstractSpan span) {
- this.span = span;
- }
-
- public AbstractSpan getSpan() {
- return this.span;
- }
-
- @Override
- public int statusCode() {
- return response.getStatusCode().value();
- }
-}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java
new file mode 100644
index 0000000..640e04c
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.skywalking.apm.plugin.spring.mvc.commons;
+
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.util.CollectionUtil;
+import org.apache.skywalking.apm.util.StringUtil;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RequestUtil {
+ public static void collectHttpParam(HttpServletRequest request,
AbstractSpan span) {
+ final Map<String, String[]> parameterMap = request.getParameterMap();
+ if (parameterMap != null && !parameterMap.isEmpty()) {
+ String tagValue = CollectionUtil.toString(parameterMap);
+ tagValue =
SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ?
+ StringUtil.cut(tagValue,
SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue;
+ Tags.HTTP.PARAMS.set(span, tagValue);
+ }
+ }
+
+ public static void collectHttpParam(ServerHttpRequest request,
AbstractSpan span) {
+ Map<String, String[]> parameterMap = new
HashMap<>(request.getQueryParams().size());
+ request.getQueryParams().forEach((key, value) -> {
+ parameterMap.put(key, value.toArray(new String[0]));
+ });
+ if (!parameterMap.isEmpty()) {
+ String tagValue = CollectionUtil.toString(parameterMap);
+ tagValue =
SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ?
+ StringUtil.cut(tagValue,
SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue;
+ Tags.HTTP.PARAMS.set(span, tagValue);
+ }
+ }
+
+ public static void collectHttpHeaders(HttpServletRequest request,
AbstractSpan span) {
+ final List<String> headersList = new
ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size());
+ SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream()
+ .filter(
+ headerName -> request.getHeaders(headerName) != null)
+ .forEach(headerName -> {
+ Enumeration<String> headerValues = request.getHeaders(
+ headerName);
+ List<String> valueList = Collections.list(
+ headerValues);
+ if (!CollectionUtil.isEmpty(valueList)) {
+ String headerValue = valueList.toString();
+ headersList.add(headerName + "=" + headerValue);
+ }
+ });
+
+ collectHttpHeaders(headersList, span);
+ }
+
+ public static void collectHttpHeaders(ServerHttpRequest request,
AbstractSpan span) {
+ final List<String> headersList = new
ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size());
+ SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream()
+ .filter(headerName -> getHeaders(request,
headerName).hasMoreElements())
+ .forEach(headerName -> {
+ Enumeration<String> headerValues = getHeaders(request,
headerName);
+ List<String> valueList = Collections.list(
+ headerValues);
+ if (!CollectionUtil.isEmpty(valueList)) {
+ String headerValue = valueList.toString();
+ headersList.add(headerName + "=" + headerValue);
+ }
+ });
+
+ collectHttpHeaders(headersList, span);
+ }
+
+ private static void collectHttpHeaders(final List<String> headersList,
final AbstractSpan span) {
+ if (headersList != null && !headersList.isEmpty()) {
+ String tagValue = String.join("\n", headersList);
+ tagValue =
SpringMVCPluginConfig.Plugin.Http.HTTP_HEADERS_LENGTH_THRESHOLD > 0 ?
+ StringUtil.cut(tagValue,
SpringMVCPluginConfig.Plugin.Http.HTTP_HEADERS_LENGTH_THRESHOLD) : tagValue;
+ Tags.HTTP.HEADERS.set(span, tagValue);
+ }
+ }
+
+ public static Enumeration<String> getHeaders(final ServerHttpRequest
request, final String headerName) {
+ List<String> values = request.getHeaders().get(headerName);
+ if (values == null) {
+ return Collections.enumeration(Collections.emptyList());
+ }
+ return Collections.enumeration(values);
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ResponseHolder.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ResponseHolder.java
deleted file mode 100644
index b46c4f2..0000000
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/ResponseHolder.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.skywalking.apm.plugin.spring.mvc.commons;
-
-public interface ResponseHolder {
- int statusCode();
-}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java
index bcfcb6d..c6121a6 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java
@@ -18,16 +18,10 @@
package org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
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.RuntimeContext;
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;
@@ -38,16 +32,20 @@ import
org.apache.skywalking.apm.agent.core.util.CollectionUtil;
import org.apache.skywalking.apm.agent.core.util.MethodUtil;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
import
org.apache.skywalking.apm.plugin.spring.mvc.commons.EnhanceRequireObjectCache;
-import org.apache.skywalking.apm.plugin.spring.mvc.commons.RequestHolder;
-import org.apache.skywalking.apm.plugin.spring.mvc.commons.ResponseHolder;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.ReactiveResponseHolder;
+import org.apache.skywalking.apm.plugin.spring.mvc.commons.RequestUtil;
import
org.apache.skywalking.apm.plugin.spring.mvc.commons.SpringMVCPluginConfig;
import
org.apache.skywalking.apm.plugin.spring.mvc.commons.exception.IllegalMethodStackDepthException;
import
org.apache.skywalking.apm.plugin.spring.mvc.commons.exception.ServletResponseNotFoundException;
-import org.apache.skywalking.apm.util.StringUtil;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.CONTROLLER_METHOD_STACK_DEPTH;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.FORWARD_REQUEST_FLAG;
+import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.REACTIVE_ASYNC_SPAN_IN_RUNTIME_CONTEXT;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.REQUEST_KEY_IN_RUNTIME_CONTEXT;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.RESPONSE_KEY_IN_RUNTIME_CONTEXT;
@@ -60,9 +58,17 @@ public abstract class AbstractMethodInterceptor implements
InstanceMethodsAround
private static final String SERVLET_RESPONSE_CLASS =
"javax.servlet.http.HttpServletResponse";
private static final String GET_STATUS_METHOD = "getStatus";
+ private static boolean IN_SERVLET_CONTAINER;
+
static {
IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist(
- AbstractMethodInterceptor.class.getClassLoader(),
SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD);
+ AbstractMethodInterceptor.class.getClassLoader(),
SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD);
+ try {
+ Class.forName(SERVLET_RESPONSE_CLASS, true,
AbstractMethodInterceptor.class.getClassLoader());
+ IN_SERVLET_CONTAINER = true;
+ } catch (Exception ignore) {
+ IN_SERVLET_CONTAINER = false;
+ }
}
public abstract String getRequestURL(Method method);
@@ -96,31 +102,58 @@ public abstract class AbstractMethodInterceptor implements
InstanceMethodsAround
operationName = getAcceptedMethodTypes(method) + requestURL;
}
- RequestHolder request = (RequestHolder)
ContextManager.getRuntimeContext()
-
.get(REQUEST_KEY_IN_RUNTIME_CONTEXT);
+ Object request =
ContextManager.getRuntimeContext().get(REQUEST_KEY_IN_RUNTIME_CONTEXT);
+
if (request != null) {
StackDepth stackDepth = (StackDepth)
ContextManager.getRuntimeContext().get(CONTROLLER_METHOD_STACK_DEPTH);
if (stackDepth == null) {
- ContextCarrier contextCarrier = new ContextCarrier();
- CarrierItem next = contextCarrier.items();
- while (next.hasNext()) {
- next = next.next();
- next.setHeadValue(request.getHeader(next.getHeadKey()));
- }
-
- AbstractSpan span =
ContextManager.createEntrySpan(operationName, contextCarrier);
- Tags.URL.set(span, request.requestURL());
- Tags.HTTP.METHOD.set(span, request.requestMethod());
- span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
- SpanLayer.asHttp(span);
-
- if
(SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) {
- collectHttpParam(request, span);
- }
-
- if
(!CollectionUtil.isEmpty(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS))
{
- collectHttpHeaders(request, span);
+ final ContextCarrier contextCarrier = new ContextCarrier();
+
+ if (IN_SERVLET_CONTAINER &&
HttpServletRequest.class.isAssignableFrom(request.getClass())) {
+ final HttpServletRequest httpServletRequest =
(HttpServletRequest) request;
+ CarrierItem next = contextCarrier.items();
+ while (next.hasNext()) {
+ next = next.next();
+
next.setHeadValue(httpServletRequest.getHeader(next.getHeadKey()));
+ }
+
+ AbstractSpan span =
ContextManager.createEntrySpan(operationName, contextCarrier);
+ Tags.URL.set(span,
httpServletRequest.getRequestURL().toString());
+ Tags.HTTP.METHOD.set(span, httpServletRequest.getMethod());
+ span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
+ SpanLayer.asHttp(span);
+
+ if
(SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) {
+ RequestUtil.collectHttpParam(httpServletRequest, span);
+ }
+
+ if
(!CollectionUtil.isEmpty(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS))
{
+ RequestUtil.collectHttpHeaders(httpServletRequest,
span);
+ }
+ } else if
(ServerHttpRequest.class.isAssignableFrom(request.getClass())) {
+ final ServerHttpRequest serverHttpRequest =
(ServerHttpRequest) request;
+ CarrierItem next = contextCarrier.items();
+ while (next.hasNext()) {
+ next = next.next();
+
next.setHeadValue(serverHttpRequest.getHeaders().getFirst(next.getHeadKey()));
+ }
+
+ AbstractSpan span =
ContextManager.createEntrySpan(operationName, contextCarrier);
+ Tags.URL.set(span, serverHttpRequest.getURI().toString());
+ Tags.HTTP.METHOD.set(span,
serverHttpRequest.getMethodValue());
+ span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
+ SpanLayer.asHttp(span);
+
+ if
(SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) {
+ RequestUtil.collectHttpParam(serverHttpRequest, span);
+ }
+
+ if
(!CollectionUtil.isEmpty(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS))
{
+ RequestUtil.collectHttpHeaders(serverHttpRequest,
span);
+ }
+ } else {
+ throw new IllegalStateException("this line should not be
reached");
}
stackDepth = new StackDepth();
@@ -136,8 +169,8 @@ public abstract class AbstractMethodInterceptor implements
InstanceMethodsAround
private String buildOperationName(Object invoker, Method method) {
StringBuilder operationName = new
StringBuilder(invoker.getClass().getName()).append(".")
-
.append(method.getName())
-
.append("(");
+ .append(method.getName())
+ .append("(");
for (Class<?> type : method.getParameterTypes()) {
operationName.append(type.getName()).append(",");
}
@@ -152,7 +185,8 @@ public abstract class AbstractMethodInterceptor implements
InstanceMethodsAround
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
- Boolean forwardRequestFlag = (Boolean)
ContextManager.getRuntimeContext().get(FORWARD_REQUEST_FLAG);
+ final RuntimeContext runtimeContext =
ContextManager.getRuntimeContext();
+ Boolean forwardRequestFlag = (Boolean)
runtimeContext.get(FORWARD_REQUEST_FLAG);
/**
* Spring MVC plugin do nothing if current request is forward request.
* Ref: https://github.com/apache/skywalking/pull/1325
@@ -161,11 +195,10 @@ public abstract class AbstractMethodInterceptor
implements InstanceMethodsAround
return ret;
}
- RequestHolder request = (RequestHolder)
ContextManager.getRuntimeContext()
-
.get(REQUEST_KEY_IN_RUNTIME_CONTEXT);
+ Object request = runtimeContext.get(REQUEST_KEY_IN_RUNTIME_CONTEXT);
if (request != null) {
- StackDepth stackDepth = (StackDepth)
ContextManager.getRuntimeContext().get(CONTROLLER_METHOD_STACK_DEPTH);
+ StackDepth stackDepth = (StackDepth)
runtimeContext.get(CONTROLLER_METHOD_STACK_DEPTH);
if (stackDepth == null) {
throw new IllegalMethodStackDepthException();
} else {
@@ -175,30 +208,43 @@ public abstract class AbstractMethodInterceptor
implements InstanceMethodsAround
AbstractSpan span = ContextManager.activeSpan();
if (stackDepth.depth() == 0) {
- ResponseHolder response = (ResponseHolder)
ContextManager.getRuntimeContext()
- .get(
-
RESPONSE_KEY_IN_RUNTIME_CONTEXT);
+ Object response =
runtimeContext.get(RESPONSE_KEY_IN_RUNTIME_CONTEXT);
if (response == null) {
throw new ServletResponseNotFoundException();
}
- if (IS_SERVLET_GET_STATUS_METHOD_EXIST &&
response.statusCode() >= 400) {
- span.errorOccurred();
- Tags.STATUS_CODE.set(span,
Integer.toString(response.statusCode()));
+ Integer statusCode = null;
+
+ if (IS_SERVLET_GET_STATUS_METHOD_EXIST &&
HttpServletResponse.class.isAssignableFrom(response.getClass())) {
+ statusCode = ((HttpServletResponse) response).getStatus();
+ } else if
(ServerHttpResponse.class.isAssignableFrom(response.getClass())) {
+ if (IS_SERVLET_GET_STATUS_METHOD_EXIST) {
+ statusCode = ((ServerHttpResponse)
response).getRawStatusCode();
+ }
+ Object context =
runtimeContext.get(REACTIVE_ASYNC_SPAN_IN_RUNTIME_CONTEXT);
+ if (context != null) {
+ ((AbstractSpan[]) context)[0] = span.prepareForAsync();
+ }
}
- if (response instanceof ReactiveResponseHolder) {
- ReactiveResponseHolder reactiveResponse =
(ReactiveResponseHolder) response;
- AbstractSpan async = span.prepareForAsync();
- reactiveResponse.setSpan(async);
+
+ if (statusCode != null && statusCode >= 400) {
+ span.errorOccurred();
+ Tags.STATUS_CODE.set(span, Integer.toString(statusCode));
}
-
ContextManager.getRuntimeContext().remove(REQUEST_KEY_IN_RUNTIME_CONTEXT);
-
ContextManager.getRuntimeContext().remove(RESPONSE_KEY_IN_RUNTIME_CONTEXT);
-
ContextManager.getRuntimeContext().remove(CONTROLLER_METHOD_STACK_DEPTH);
+
+ runtimeContext.remove(REACTIVE_ASYNC_SPAN_IN_RUNTIME_CONTEXT);
+ runtimeContext.remove(REQUEST_KEY_IN_RUNTIME_CONTEXT);
+ runtimeContext.remove(RESPONSE_KEY_IN_RUNTIME_CONTEXT);
+ runtimeContext.remove(CONTROLLER_METHOD_STACK_DEPTH);
}
// Active HTTP parameter collection automatically in the profiling
context.
if (!SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS &&
span.isProfiling()) {
- collectHttpParam(request, span);
+ if
(HttpServletRequest.class.isAssignableFrom(request.getClass())) {
+ RequestUtil.collectHttpParam((HttpServletRequest) request,
span);
+ } else if
(ServerHttpRequest.class.isAssignableFrom(request.getClass())) {
+ RequestUtil.collectHttpParam((ServerHttpRequest) request,
span);
+ }
}
ContextManager.stopSpan();
@@ -212,38 +258,4 @@ public abstract class AbstractMethodInterceptor implements
InstanceMethodsAround
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().log(t);
}
-
- private void collectHttpParam(RequestHolder request, AbstractSpan span) {
- final Map<String, String[]> parameterMap = request.getParameterMap();
- if (parameterMap != null && !parameterMap.isEmpty()) {
- String tagValue = CollectionUtil.toString(parameterMap);
- tagValue =
SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ?
- StringUtil.cut(tagValue,
SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue;
- Tags.HTTP.PARAMS.set(span, tagValue);
- }
- }
-
- private void collectHttpHeaders(RequestHolder request, AbstractSpan span) {
- final List<String> headersList = new
ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size());
- SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream()
- .filter(
- headerName
-> request.getHeaders(headerName) != null)
-
.forEach(headerName -> {
-
Enumeration<String> headerValues = request.getHeaders(
-
headerName);
- List<String>
valueList = Collections.list(
-
headerValues);
- if
(!CollectionUtil.isEmpty(valueList)) {
- String
headerValue = valueList.toString();
-
headersList.add(headerName + "=" + headerValue);
- }
- });
-
- if (!headersList.isEmpty()) {
- String tagValue =
headersList.stream().collect(Collectors.joining("\n"));
- tagValue =
SpringMVCPluginConfig.Plugin.Http.HTTP_HEADERS_LENGTH_THRESHOLD > 0 ?
- StringUtil.cut(tagValue,
SpringMVCPluginConfig.Plugin.Http.HTTP_HEADERS_LENGTH_THRESHOLD) : tagValue;
- Tags.HTTP.HEADERS.set(span, tagValue);
- }
- }
}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/GetBeanInterceptor.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/GetBeanInterceptor.java
index 3fd2d61..6cc6c62 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/GetBeanInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/GetBeanInterceptor.java
@@ -23,7 +23,6 @@ import
org.apache.skywalking.apm.agent.core.context.ContextManager;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.JavaxServletRequestHolder;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@@ -45,8 +44,8 @@ public class GetBeanInterceptor implements
InstanceMethodsAroundInterceptor {
Object ret) throws Throwable {
if (ret instanceof EnhancedInstance) {
ContextManager.getRuntimeContext()
- .put(REQUEST_KEY_IN_RUNTIME_CONTEXT, new
JavaxServletRequestHolder(((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes())
- .getRequest()));
+ .put(REQUEST_KEY_IN_RUNTIME_CONTEXT,
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
+ .getRequest());
}
return ret;
}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/InvokeForRequestInterceptor.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/InvokeForRequestInterceptor.java
index 4360048..9d9b915 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/InvokeForRequestInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/InvokeForRequestInterceptor.java
@@ -19,12 +19,10 @@
package org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor;
import java.lang.reflect.Method;
-import javax.servlet.http.HttpServletResponse;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.JavaxServletResponseHolder;
import org.springframework.web.context.request.NativeWebRequest;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.RESPONSE_KEY_IN_RUNTIME_CONTEXT;
@@ -38,8 +36,7 @@ public class InvokeForRequestInterceptor implements
InstanceMethodsAroundInterce
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
ContextManager.getRuntimeContext()
- .put(RESPONSE_KEY_IN_RUNTIME_CONTEXT, new
JavaxServletResponseHolder(
- (HttpServletResponse) ((NativeWebRequest)
allArguments[0]).getNativeResponse()));
+ .put(RESPONSE_KEY_IN_RUNTIME_CONTEXT, ((NativeWebRequest)
allArguments[0]).getNativeResponse());
}
@Override
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/InvokeHandlerMethodInterceptor.java
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/InvokeHandlerMethodInterceptor.java
index 9d7df03..bc6e2f9 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/InvokeHandlerMethodInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/InvokeHandlerMethodInterceptor.java
@@ -18,15 +18,12 @@
package org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor;
-import java.lang.reflect.Method;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.JavaxServletRequestHolder;
-import
org.apache.skywalking.apm.plugin.spring.mvc.commons.JavaxServletResponseHolder;
+
+import java.lang.reflect.Method;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.REQUEST_KEY_IN_RUNTIME_CONTEXT;
import static
org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.RESPONSE_KEY_IN_RUNTIME_CONTEXT;
@@ -36,10 +33,8 @@ public class InvokeHandlerMethodInterceptor implements
InstanceMethodsAroundInte
public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
if (allArguments[2] instanceof EnhancedInstance) {
-
ContextManager.getRuntimeContext().put(RESPONSE_KEY_IN_RUNTIME_CONTEXT, new
JavaxServletResponseHolder(
- (HttpServletResponse) allArguments[1]));
-
ContextManager.getRuntimeContext().put(REQUEST_KEY_IN_RUNTIME_CONTEXT, new
JavaxServletRequestHolder(
- (HttpServletRequest) allArguments[0]));
+
ContextManager.getRuntimeContext().put(RESPONSE_KEY_IN_RUNTIME_CONTEXT,
allArguments[1]);
+
ContextManager.getRuntimeContext().put(REQUEST_KEY_IN_RUNTIME_CONTEXT,
allArguments[0]);
}
}
diff --git
a/test/plugin/scenarios/springmvc-reactive-devtools-scenario/bin/startup.sh
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/bin/startup.sh
new file mode 100644
index 0000000..db12139
--- /dev/null
+++ b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/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.
+
+set -ex
+
+home="$(cd "$(dirname $0)"; pwd)"
+
+classpath="$(printf %s:
$home/../target/3rd-lib/*.jar)${home}/../target/classes"
+java ${agent_opts} -classpath "$classpath"
test.apache.skywalking.apm.testcase.sc.springmvcreactive.Application &
diff --git
a/test/plugin/scenarios/springmvc-reactive-devtools-scenario/config/expectedData.yaml
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/config/expectedData.yaml
new file mode 100644
index 0000000..95dd650
--- /dev/null
+++
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/config/expectedData.yaml
@@ -0,0 +1,103 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT 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: springmvc-reactive-devtools-scenario
+ segmentSize: ge 2
+ segments:
+ - segmentId: not null
+ spans:
+ - operationName: H2/JDBI/PreparedStatement/executeQuery
+ operationId: 0
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Database
+ startTime: not null
+ endTime: not null
+ componentId: 32
+ isError: false
+ spanType: Exit
+ peer: not null
+ tags:
+ - {key: db.type, value: not null}
+ - {key: db.instance, value: test}
+ - {key: db.statement, value: not null}
+ skipAnalysis: 'false'
+ - operationName: '/testcase/error'
+ operationId: 0
+ parentSpanId: 0
+ spanId: 2
+ spanLayer: Http
+ startTime: not null
+ endTime: not null
+ isError: false
+ componentId: not null
+ tags:
+ - {key: url, value: not null}
+ - {key: http.method, value: GET}
+ skipAnalysis: 'false'
+ - operationName: 'future/get:/testcase/error'
+ operationId: 0
+ parentSpanId: 0
+ spanId: 3
+ spanLayer: not null
+ startTime: not null
+ endTime: not null
+ isError: true
+ componentId: not null
+ logs:
+ - logEvent:
+ - {key: event, value: error}
+ - {key: error.kind, value: not null}
+ - {key: message, value: not null}
+ - {key: stack, value: not null}
+ skipAnalysis: 'false'
+ - operationName: '{GET}/testcase/{test}'
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: not null
+ endTime: not null
+ componentId: 14
+ isError: false
+ tags:
+ - {key: url, value: not null}
+ - {key: http.method, value: GET}
+ skipAnalysis: 'false'
+ - segmentId: not null
+ spans:
+ - operationName: '{GET}/testcase/error'
+ operationId: 0
+ parentSpanId: -1
+ spanId: 0
+ spanLayer: Http
+ startTime: not null
+ endTime: not null
+ componentId: 14
+ spanType: Entry
+ isError: true
+ tags:
+ - {key: url, value: not null}
+ - {key: http.method, value: GET}
+ - {key: status_code, value: '500'}
+ logs:
+ - logEvent:
+ - {key: event, value: error}
+ - {key: error.kind, value: not null}
+ - {key: message, value: not null}
+ - {key: stack, value: not null}
+ skipAnalysis: 'false'
\ No newline at end of file
diff --git
a/test/plugin/scenarios/springmvc-reactive-devtools-scenario/configuration.yml
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/configuration.yml
new file mode 100644
index 0000000..12cb454
--- /dev/null
+++
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/configuration.yml
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+type: jvm
+entryService: http://localhost:8080/testcase/test
+healthCheck: http://localhost:8080/testcase/healthCheck
+startScript: ./bin/startup.sh
diff --git a/test/plugin/scenarios/springmvc-reactive-scenario/pom.xml
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/pom.xml
similarity index 71%
copy from test/plugin/scenarios/springmvc-reactive-scenario/pom.xml
copy to test/plugin/scenarios/springmvc-reactive-devtools-scenario/pom.xml
index aa3c075..05badf7 100644
--- a/test/plugin/scenarios/springmvc-reactive-scenario/pom.xml
+++ b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/pom.xml
@@ -22,11 +22,11 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.skywalking</groupId>
- <artifactId>springmvc-reactive-scenario</artifactId>
+ <artifactId>springmvc-reactive-devtools-scenario</artifactId>
<packaging>jar</packaging>
<version>5.0.0</version>
- <name>skywalking-springmvc-reactive-scenario</name>
+ <name>skywalking-springmvc-reactive-devtools-scenario</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -41,6 +41,12 @@
<version>${test.framework.version}</version>
</dependency>
<dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-devtools</artifactId>
+ <optional>true</optional>
+ <version>${test.framework.version}</version>
+ </dependency>
+ <dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
@@ -48,10 +54,31 @@
</dependencies>
<build>
- <finalName>springmvc-reactive-scenario</finalName>
+ <finalName>springmvc-reactive-devtools-scenario</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <type>jar</type>
+ <includeTypes>jar</includeTypes>
+ <includeScope>runtime</includeScope>
+ <outputDirectory>
+ ${project.build.directory}/3rd-lib/
+ </outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
@@ -63,7 +90,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
- <version>1.5.9.RELEASE</version>
+ <version>${test.framework.version}</version>
<executions>
<execution>
<goals>
diff --git
a/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/assembly/assembly.xml
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 0000000..5e8d436
--- /dev/null
+++
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+<assembly
+
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <fileSets>
+ <fileSet>
+ <directory>./bin</directory>
+ <fileMode>0775</fileMode>
+ </fileSet>
+ <fileSet>
+ <directory>${project.build.directory}/classes</directory>
+ <fileMode>0775</fileMode>
+ </fileSet>
+ <fileSet>
+ <directory>${project.build.directory}/3rd-lib</directory>
+ <fileMode>0775</fileMode>
+ </fileSet>
+ </fileSets>
+
+ <files>
+ <file>
+
<source>${project.build.directory}/springmvc-reactive-devtools-scenario.jar</source>
+ <outputDirectory>./libs</outputDirectory>
+ <fileMode>0775</fileMode>
+ </file>
+ </files>
+</assembly>
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestHolder.java
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/springmvcreactive/Application.java
similarity index 70%
rename from
apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestHolder.java
rename to
test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/springmvcreactive/Application.java
index 8f4c933..4d6eae3 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestHolder.java
+++
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/springmvcreactive/Application.java
@@ -15,19 +15,15 @@
* limitations under the License.
*/
-package org.apache.skywalking.apm.plugin.spring.mvc.commons;
+package test.apache.skywalking.apm.testcase.sc.springmvcreactive;
-import java.util.Enumeration;
-import java.util.Map;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
-public interface RequestHolder {
- String getHeader(String headerName);
+@SpringBootApplication
+public class Application {
- Enumeration<String> getHeaders(String headerName);
-
- String requestURL();
-
- String requestMethod();
-
- Map<String, String[]> getParameterMap();
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
}
diff --git
a/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/springmvcreactive/controller/Controller.java
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/springmvcreactive/controller/Controller.java
new file mode 100644
index 0000000..0117cad
--- /dev/null
+++
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/springmvcreactive/controller/Controller.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package test.apache.skywalking.apm.testcase.sc.springmvcreactive.controller;
+
+import java.sql.SQLException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.concurrent.ListenableFuture;
+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;
+import org.springframework.web.client.AsyncRestTemplate;
+import reactor.core.publisher.Mono;
+import
test.apache.skywalking.apm.testcase.sc.springmvcreactive.service.TestService;
+
+@RestController
+public class Controller {
+
+ @Autowired
+ private TestService testService;
+
+ @RequestMapping("/testcase/healthCheck")
+ public String healthCheck() {
+ return "healthCheck";
+ }
+
+ @GetMapping("/testcase/{test}")
+ public Mono<String> hello(@RequestBody(required = false) String body,
@PathVariable("test") String test) throws SQLException {
+ testService.executeSQL();
+ ListenableFuture<ResponseEntity<String>> forEntity = new
AsyncRestTemplate().getForEntity("http://localhost:8080/testcase/error",
String.class);
+ try {
+ forEntity.get();
+ } catch (Exception e) {
+ }
+ return Mono.just("Hello World");
+ }
+
+ @GetMapping("/testcase/error")
+ public Mono<String> error() {
+ throw new RuntimeException("this is Error");
+ }
+
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/JavaxServletResponseHolder.java
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/springmvcreactive/service/TestService.java
similarity index 54%
rename from
apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/JavaxServletResponseHolder.java
rename to
test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/springmvcreactive/service/TestService.java
index 7fc0144..aff108f 100644
---
a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/JavaxServletResponseHolder.java
+++
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/java/test/apache/skywalking/apm/testcase/sc/springmvcreactive/service/TestService.java
@@ -15,21 +15,28 @@
* limitations under the License.
*/
-package org.apache.skywalking.apm.plugin.spring.mvc.commons;
+package test.apache.skywalking.apm.testcase.sc.springmvcreactive.service;
-import javax.servlet.http.HttpServletResponse;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import javax.annotation.PostConstruct;
+import org.springframework.stereotype.Service;
-public class JavaxServletResponseHolder implements ResponseHolder {
+@Service
+public class TestService {
- private final HttpServletResponse response;
+ private Connection connection;
- public JavaxServletResponseHolder(final HttpServletResponse response) {
- this.response = response;
+ @PostConstruct
+ private void setUp() throws SQLException {
+ connection =
DriverManager.getConnection("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", "");
}
- @Override
- public int statusCode() {
- return response.getStatus();
+ public void executeSQL() throws SQLException {
+ PreparedStatement preparedStatement =
connection.prepareStatement("SELECT 1 = 1");
+ preparedStatement.executeQuery();
}
}
diff --git
a/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/resources/application.yml
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/resources/application.yml
new file mode 100644
index 0000000..e916bcd
--- /dev/null
+++
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/src/main/resources/application.yml
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+server.port: 8080
\ No newline at end of file
diff --git
a/test/plugin/scenarios/springmvc-reactive-devtools-scenario/support-version.list
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/support-version.list
new file mode 100644
index 0000000..c5820da
--- /dev/null
+++
b/test/plugin/scenarios/springmvc-reactive-devtools-scenario/support-version.list
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# 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
diff --git a/test/plugin/scenarios/springmvc-reactive-scenario/pom.xml
b/test/plugin/scenarios/springmvc-reactive-scenario/pom.xml
index aa3c075..9459d98 100644
--- a/test/plugin/scenarios/springmvc-reactive-scenario/pom.xml
+++ b/test/plugin/scenarios/springmvc-reactive-scenario/pom.xml
@@ -63,7 +63,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
- <version>1.5.9.RELEASE</version>
+ <version>${test.framework.version}</version>
<executions>
<execution>
<goals>