Skip to content

Commit 606c563

Browse files
authored
Eliminate repeated code with HttpServletRequestWrapper in mvc-annotation-commons. (#776)
1 parent bf2daf3 commit 606c563

File tree

5 files changed

+230
-57
lines changed

5 files changed

+230
-57
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Release Notes.
1717
* Fix OOM due to too many span logs.
1818
* Fix ClassLoader cache OOM issue with WeakHashMap.
1919
* Fix Jetty client cannot receive the HTTP response body.
20+
* Eliminate repeated code with HttpServletRequestWrapper in mvc-annotation-commons.
2021

2122
All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1)
2223

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package org.apache.skywalking.apm.plugin.spring.mvc.commons;
20+
21+
import java.util.Enumeration;
22+
import java.util.Map;
23+
24+
public interface HttpServletRequestWrapper {
25+
26+
String getHeader(String name);
27+
28+
String getMethod();
29+
30+
StringBuffer getRequestURL();
31+
32+
String getRemoteHost();
33+
34+
Map<String, String[]> getParameterMap();
35+
36+
public Enumeration<String> getHeaders(String name);
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package org.apache.skywalking.apm.plugin.spring.mvc.commons;
20+
21+
import java.util.Enumeration;
22+
import java.util.Map;
23+
24+
public class HttpServletRequestWrappers {
25+
26+
public static HttpServletRequestWrapper wrap(jakarta.servlet.http.HttpServletRequest request) {
27+
return new JakartaHttpServletRequest(request);
28+
}
29+
30+
public static HttpServletRequestWrapper wrap(javax.servlet.http.HttpServletRequest request) {
31+
return new JavaxHttpServletRequest(request);
32+
}
33+
34+
public static class JakartaHttpServletRequest implements HttpServletRequestWrapper {
35+
36+
private jakarta.servlet.http.HttpServletRequest jakartaRequest;
37+
38+
public JakartaHttpServletRequest(jakarta.servlet.http.HttpServletRequest jakartaRequest) {
39+
this.jakartaRequest = jakartaRequest;
40+
}
41+
42+
@Override
43+
public String getHeader(String name) {
44+
return jakartaRequest.getHeader(name);
45+
}
46+
47+
@Override
48+
public String getMethod() {
49+
return jakartaRequest.getMethod();
50+
}
51+
52+
@Override
53+
public StringBuffer getRequestURL() {
54+
return jakartaRequest.getRequestURL();
55+
}
56+
57+
@Override
58+
public String getRemoteHost() {
59+
return jakartaRequest.getRemoteHost();
60+
}
61+
62+
@Override
63+
public Map<String, String[]> getParameterMap() {
64+
return jakartaRequest.getParameterMap();
65+
}
66+
67+
@Override
68+
public Enumeration<String> getHeaders(String name) {
69+
return jakartaRequest.getHeaders(name);
70+
}
71+
72+
}
73+
74+
public static class JavaxHttpServletRequest implements HttpServletRequestWrapper {
75+
private javax.servlet.http.HttpServletRequest javaxRequest;
76+
77+
public JavaxHttpServletRequest(javax.servlet.http.HttpServletRequest javaxRequest) {
78+
this.javaxRequest = javaxRequest;
79+
}
80+
81+
@Override
82+
public String getHeader(String name) {
83+
return javaxRequest.getHeader(name);
84+
}
85+
86+
@Override
87+
public String getMethod() {
88+
return javaxRequest.getMethod();
89+
}
90+
91+
@Override
92+
public StringBuffer getRequestURL() {
93+
return javaxRequest.getRequestURL();
94+
}
95+
96+
@Override
97+
public String getRemoteHost() {
98+
return javaxRequest.getRemoteHost();
99+
}
100+
101+
@Override
102+
public Map<String, String[]> getParameterMap() {
103+
return javaxRequest.getParameterMap();
104+
}
105+
106+
@Override
107+
public Enumeration<String> getHeaders(String name) {
108+
return javaxRequest.getHeaders(name);
109+
}
110+
111+
}
112+
}

apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/RequestUtil.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ public static void collectHttpParam(jakarta.servlet.http.HttpServletRequest requ
5252
}
5353
}
5454

55+
public static void collectHttpParam(HttpServletRequestWrapper request, AbstractSpan span) {
56+
final Map<String, String[]> parameterMap = request.getParameterMap();
57+
if (parameterMap != null && !parameterMap.isEmpty()) {
58+
String tagValue = CollectionUtil.toString(parameterMap);
59+
tagValue = SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD > 0 ?
60+
StringUtil.cut(tagValue, SpringMVCPluginConfig.Plugin.Http.HTTP_PARAMS_LENGTH_THRESHOLD) : tagValue;
61+
Tags.HTTP.PARAMS.set(span, tagValue);
62+
}
63+
}
64+
5565
public static void collectHttpParam(ServerHttpRequest request, AbstractSpan span) {
5666
Map<String, String[]> parameterMap = new HashMap<>(request.getQueryParams().size());
5767
request.getQueryParams().forEach((key, value) -> {
@@ -65,6 +75,25 @@ public static void collectHttpParam(ServerHttpRequest request, AbstractSpan span
6575
}
6676
}
6777

78+
public static void collectHttpHeaders(HttpServletRequestWrapper request, AbstractSpan span) {
79+
final List<String> headersList = new ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size());
80+
SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream()
81+
.filter(
82+
headerName -> request.getHeaders(headerName) != null)
83+
.forEach(headerName -> {
84+
Enumeration<String> headerValues = request.getHeaders(
85+
headerName);
86+
List<String> valueList = Collections.list(
87+
headerValues);
88+
if (!CollectionUtil.isEmpty(valueList)) {
89+
String headerValue = valueList.toString();
90+
headersList.add(headerName + "=" + headerValue);
91+
}
92+
});
93+
94+
collectHttpHeaders(headersList, span);
95+
}
96+
6897
public static void collectHttpHeaders(HttpServletRequest request, AbstractSpan span) {
6998
final List<String> headersList = new ArrayList<>(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.size());
7099
SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS.stream()

apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java

Lines changed: 51 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
package org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor;
2020

21+
import java.lang.reflect.Method;
22+
import javax.servlet.http.HttpServletRequest;
23+
import javax.servlet.http.HttpServletResponse;
2124
import org.apache.skywalking.apm.agent.core.context.CarrierItem;
2225
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
2326
import org.apache.skywalking.apm.agent.core.context.ContextManager;
@@ -34,17 +37,15 @@
3437
import org.apache.skywalking.apm.agent.core.util.MethodUtil;
3538
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
3639
import org.apache.skywalking.apm.plugin.spring.mvc.commons.EnhanceRequireObjectCache;
40+
import org.apache.skywalking.apm.plugin.spring.mvc.commons.HttpServletRequestWrapper;
41+
import org.apache.skywalking.apm.plugin.spring.mvc.commons.HttpServletRequestWrappers;
3742
import org.apache.skywalking.apm.plugin.spring.mvc.commons.RequestUtil;
3843
import org.apache.skywalking.apm.plugin.spring.mvc.commons.SpringMVCPluginConfig;
3944
import org.apache.skywalking.apm.plugin.spring.mvc.commons.exception.IllegalMethodStackDepthException;
4045
import org.apache.skywalking.apm.plugin.spring.mvc.commons.exception.ServletResponseNotFoundException;
4146
import org.springframework.http.server.reactive.ServerHttpRequest;
4247
import org.springframework.http.server.reactive.ServerHttpResponse;
4348

44-
import javax.servlet.http.HttpServletRequest;
45-
import javax.servlet.http.HttpServletResponse;
46-
import java.lang.reflect.Method;
47-
4849
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.CONTROLLER_METHOD_STACK_DEPTH;
4950
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.FORWARD_REQUEST_FLAG;
5051
import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.REACTIVE_ASYNC_SPAN_IN_RUNTIME_CONTEXT;
@@ -68,10 +69,11 @@ public abstract class AbstractMethodInterceptor implements InstanceMethodsAround
6869

6970
static {
7071
IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist(
71-
AbstractMethodInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD);
72+
AbstractMethodInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD);
7273
IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist(
73-
AbstractMethodInterceptor.class.getClassLoader(),
74-
JAKARTA_SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD);
74+
AbstractMethodInterceptor.class.getClassLoader(),
75+
JAKARTA_SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD
76+
);
7577
try {
7678
Class.forName(SERVLET_RESPONSE_CLASS, true, AbstractMethodInterceptor.class.getClassLoader());
7779
IN_SERVLET_CONTAINER = true;
@@ -113,53 +115,15 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr
113115

114116
if (IN_SERVLET_CONTAINER && IS_JAVAX && HttpServletRequest.class.isAssignableFrom(request.getClass())) {
115117
final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
116-
CarrierItem next = contextCarrier.items();
117-
while (next.hasNext()) {
118-
next = next.next();
119-
next.setHeadValue(httpServletRequest.getHeader(next.getHeadKey()));
120-
}
121-
122-
String operationName = this.buildOperationName(method, httpServletRequest.getMethod(),
123-
(EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField());
124-
AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier);
125-
Tags.URL.set(span, httpServletRequest.getRequestURL().toString());
126-
Tags.HTTP.METHOD.set(span, httpServletRequest.getMethod());
127-
span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
128-
SpanLayer.asHttp(span);
118+
handleBeforeMethod(
119+
objInst, method, HttpServletRequestWrappers.wrap(httpServletRequest), contextCarrier);
129120

130-
if (SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) {
131-
RequestUtil.collectHttpParam(httpServletRequest, span);
132-
}
133-
134-
if (!CollectionUtil.isEmpty(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS)) {
135-
RequestUtil.collectHttpHeaders(httpServletRequest, span);
136-
}
137-
} else if (IN_SERVLET_CONTAINER && IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom(request.getClass())) {
121+
} else if (IN_SERVLET_CONTAINER && IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom(
122+
request.getClass())) {
138123
final jakarta.servlet.http.HttpServletRequest httpServletRequest = (jakarta.servlet.http.HttpServletRequest) request;
139-
CarrierItem next = contextCarrier.items();
140-
while (next.hasNext()) {
141-
next = next.next();
142-
next.setHeadValue(httpServletRequest.getHeader(next.getHeadKey()));
143-
}
144-
145-
String operationName =
146-
this.buildOperationName(method, httpServletRequest.getMethod(),
147-
(EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField());
148-
AbstractSpan span =
149-
ContextManager.createEntrySpan(operationName, contextCarrier);
150-
Tags.URL.set(span, httpServletRequest.getRequestURL().toString());
151-
Tags.HTTP.METHOD.set(span, httpServletRequest.getMethod());
152-
span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
153-
SpanLayer.asHttp(span);
154-
155-
if (SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) {
156-
RequestUtil.collectHttpParam(httpServletRequest, span);
157-
}
124+
handleBeforeMethod(
125+
objInst, method, HttpServletRequestWrappers.wrap(httpServletRequest), contextCarrier);
158126

159-
if (!CollectionUtil
160-
.isEmpty(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS)) {
161-
RequestUtil.collectHttpHeaders(httpServletRequest, span);
162-
}
163127
} else if (ServerHttpRequest.class.isAssignableFrom(request.getClass())) {
164128
final ServerHttpRequest serverHttpRequest = (ServerHttpRequest) request;
165129
CarrierItem next = contextCarrier.items();
@@ -168,8 +132,10 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr
168132
next.setHeadValue(serverHttpRequest.getHeaders().getFirst(next.getHeadKey()));
169133
}
170134

171-
String operationName = this.buildOperationName(method, serverHttpRequest.getMethod().name(),
172-
(EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField());
135+
String operationName = this.buildOperationName(
136+
method, serverHttpRequest.getMethod().name(),
137+
(EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField()
138+
);
173139
AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier);
174140
Tags.URL.set(span, serverHttpRequest.getURI().toString());
175141
Tags.HTTP.METHOD.set(span, serverHttpRequest.getMethod().name());
@@ -198,6 +164,31 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr
198164
}
199165
}
200166

167+
private void handleBeforeMethod(EnhancedInstance objInst, Method method,
168+
HttpServletRequestWrapper httpServletRequest, ContextCarrier contextCarrier) {
169+
CarrierItem next = contextCarrier.items();
170+
while (next.hasNext()) {
171+
next = next.next();
172+
next.setHeadValue(httpServletRequest.getHeader(next.getHeadKey()));
173+
}
174+
175+
String operationName = this.buildOperationName(
176+
method, httpServletRequest.getMethod(), (EnhanceRequireObjectCache) objInst.getSkyWalkingDynamicField());
177+
AbstractSpan span = ContextManager.createEntrySpan(operationName, contextCarrier);
178+
Tags.URL.set(span, httpServletRequest.getRequestURL().toString());
179+
Tags.HTTP.METHOD.set(span, httpServletRequest.getMethod());
180+
span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
181+
SpanLayer.asHttp(span);
182+
183+
if (SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS) {
184+
RequestUtil.collectHttpParam(httpServletRequest, span);
185+
}
186+
187+
if (!CollectionUtil.isEmpty(SpringMVCPluginConfig.Plugin.Http.INCLUDE_HTTP_HEADERS)) {
188+
RequestUtil.collectHttpHeaders(httpServletRequest, span);
189+
}
190+
}
191+
201192
@Override
202193
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
203194
Object ret) throws Throwable {
@@ -232,9 +223,11 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA
232223

233224
Integer statusCode = null;
234225

235-
if (IS_SERVLET_GET_STATUS_METHOD_EXIST && HttpServletResponse.class.isAssignableFrom(response.getClass())) {
226+
if (IS_SERVLET_GET_STATUS_METHOD_EXIST && HttpServletResponse.class.isAssignableFrom(
227+
response.getClass())) {
236228
statusCode = ((HttpServletResponse) response).getStatus();
237-
} else if (IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST && jakarta.servlet.http.HttpServletResponse.class.isAssignableFrom(response.getClass())) {
229+
} else if (IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST && jakarta.servlet.http.HttpServletResponse.class.isAssignableFrom(
230+
response.getClass())) {
238231
statusCode = ((jakarta.servlet.http.HttpServletResponse) response).getStatus();
239232
} else if (ServerHttpResponse.class.isAssignableFrom(response.getClass())) {
240233
if (IS_SERVLET_GET_STATUS_METHOD_EXIST || IS_JAKARTA_SERVLET_GET_STATUS_METHOD_EXIST) {
@@ -263,7 +256,8 @@ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA
263256
if (!SpringMVCPluginConfig.Plugin.SpringMVC.COLLECT_HTTP_PARAMS && span.isProfiling()) {
264257
if (IS_JAVAX && HttpServletRequest.class.isAssignableFrom(request.getClass())) {
265258
RequestUtil.collectHttpParam((HttpServletRequest) request, span);
266-
} else if (IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom(request.getClass())) {
259+
} else if (IS_JAKARTA && jakarta.servlet.http.HttpServletRequest.class.isAssignableFrom(
260+
request.getClass())) {
267261
RequestUtil.collectHttpParam((jakarta.servlet.http.HttpServletRequest) request, span);
268262
} else if (ServerHttpRequest.class.isAssignableFrom(request.getClass())) {
269263
RequestUtil.collectHttpParam((ServerHttpRequest) request, span);
@@ -309,7 +303,7 @@ private String buildOperationName(Method method, String httpMethod, EnhanceRequi
309303
pathMappingCache.addPathMapping(method, requestURL);
310304
requestURL = pathMappingCache.findPathMapping(method);
311305
}
312-
operationName = String.join(":", httpMethod, requestURL);
306+
operationName = String.join(":", httpMethod, requestURL);
313307
}
314308

315309
return operationName;

0 commit comments

Comments
 (0)