Skip to content

Commit dc9f7d1

Browse files
authored
support jersey rest framework (#520)
1 parent 3ad9f24 commit dc9f7d1

42 files changed

Lines changed: 1826 additions & 2 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/plugins-jdk17-test.0.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ jobs:
5757
case:
5858
- jdk17-with-gson-scenario
5959
- resttemplate-6.x-scenario
60+
- jersey-3.x-scenario
6061
- jetty-thread-pool-scenario
6162
- jetty-11.x-thread-pool-scenario
6263
steps:

.github/workflows/plugins-test.2.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ jobs:
7777
- cxf-scenario
7878
- okhttp2-scenario
7979
- rocketmq-scenario
80+
- jersey-2.0.x-2.25.x-scenario
81+
- jersey-2.26.x-2.39.x-scenario
8082
steps:
8183
- uses: actions/checkout@v2
8284
with:

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Release Notes.
99
* Support ForkJoinPool trace
1010
* Support clickhouse-jdbc-plugin trace sql parameters
1111
* Support monitor jetty server work thread pool metric
12+
* Support Jersey REST framework
1213

1314
#### Documentation
1415

apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,15 +196,15 @@ public class ComponentsDefine {
196196
public static final OfficialComponent DOLPHIN_SCHEDULER = new OfficialComponent(106, "dolphinscheduler");
197197

198198
public static final OfficialComponent JSON_RPC = new OfficialComponent(107, "JsonRpc");
199-
199+
200200
public static final OfficialComponent SEATA = new OfficialComponent(108, "Seata");
201201

202202
public static final OfficialComponent MYBATIS = new OfficialComponent(109, "MyBatis");
203203

204204
public static final OfficialComponent NEO4J = new OfficialComponent(112, "Neo4j");
205205

206206
public static final OfficialComponent SENTINEL = new OfficialComponent(113, "Sentinel");
207-
207+
208208
public static final OfficialComponent GUAVA_CACHE = new OfficialComponent(114, "GuavaCache");
209209

210210
public static final OfficialComponent ALIBABA_DRUID = new OfficialComponent(115, "AlibabaDruid");
@@ -233,4 +233,6 @@ public class ComponentsDefine {
233233

234234
public static final OfficialComponent MICROMETER = new OfficialComponent(141, "Micrometer");
235235

236+
public static final OfficialComponent JERSEY = new OfficialComponent(146, "Jersey");
237+
236238
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one or more
4+
~ contributor license agreements. See the NOTICE file distributed with
5+
~ this work for additional information regarding copyright ownership.
6+
~ The ASF licenses this file to You under the Apache License, Version 2.0
7+
~ (the "License"); you may not use this file except in compliance with
8+
~ the License. You may obtain a copy of the License at
9+
~
10+
~ http://www.apache.org/licenses/LICENSE-2.0
11+
~
12+
~ Unless required by applicable law or agreed to in writing, software
13+
~ distributed under the License is distributed on an "AS IS" BASIS,
14+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
~ See the License for the specific language governing permissions and
16+
~ limitations under the License.
17+
~
18+
-->
19+
20+
<project xmlns="http://maven.apache.org/POM/4.0.0"
21+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
23+
<parent>
24+
<artifactId>apm-sdk-plugin</artifactId>
25+
<groupId>org.apache.skywalking</groupId>
26+
<version>8.16.0-SNAPSHOT</version>
27+
</parent>
28+
<modelVersion>4.0.0</modelVersion>
29+
30+
<artifactId>apm-jersey-2.x-plugin</artifactId>
31+
32+
33+
<dependencies>
34+
<dependency>
35+
<groupId>org.glassfish.jersey.core</groupId>
36+
<artifactId>jersey-server</artifactId>
37+
<version>2.21</version>
38+
<scope>provided</scope>
39+
</dependency>
40+
</dependencies>
41+
42+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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.jersey.v2;
20+
21+
import java.lang.reflect.Method;
22+
import java.util.List;
23+
import java.util.Map;
24+
import org.apache.skywalking.apm.agent.core.context.CarrierItem;
25+
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
26+
import org.apache.skywalking.apm.agent.core.context.ContextManager;
27+
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
28+
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
29+
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
30+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
31+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
32+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
33+
import org.apache.skywalking.apm.agent.core.util.CollectionUtil;
34+
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
35+
import org.glassfish.jersey.server.ContainerRequest;
36+
37+
public class ApplicationHandlerInterceptor implements InstanceMethodsAroundInterceptor {
38+
39+
@Override
40+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
41+
MethodInterceptResult result) throws Throwable {
42+
ContainerRequest request = (ContainerRequest) allArguments[0];
43+
final ContextCarrier carrier = new ContextCarrier();
44+
CarrierItem items = carrier.items();
45+
while (items.hasNext()) {
46+
items = items.next();
47+
Map<String, List<String>> headerMap = request.getHeaders();
48+
List<String> values = headerMap.get(items.getHeadKey());
49+
if (!CollectionUtil.isEmpty(values)) {
50+
items.setHeadValue(values.get(0));
51+
}
52+
}
53+
String operationName = String.join(":", request.getMethod(), request.getPath(false));
54+
final AbstractSpan span = ContextManager.createEntrySpan(operationName, carrier);
55+
final String url = request.getRequestUri().toString();
56+
Tags.URL.set(span, url);
57+
Tags.HTTP.METHOD.set(span, request.getMethod());
58+
span.setComponent(ComponentsDefine.JERSEY);
59+
SpanLayer.asHttp(span);
60+
}
61+
62+
@Override
63+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
64+
Object ret) throws Throwable {
65+
ContextManager.stopSpan();
66+
return ret;
67+
}
68+
69+
@Override
70+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
71+
Class<?>[] argumentsTypes, Throwable t) {
72+
ContextManager.activeSpan().log(t);
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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.jersey.v2.define;
20+
21+
import static net.bytebuddy.matcher.ElementMatchers.named;
22+
import static net.bytebuddy.matcher.ElementMatchers.returns;
23+
24+
import java.util.Collections;
25+
import java.util.List;
26+
import net.bytebuddy.description.method.MethodDescription;
27+
import net.bytebuddy.matcher.ElementMatcher;
28+
import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod;
29+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
30+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
31+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
32+
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
33+
import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
34+
35+
public class ApplicationHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
36+
37+
private static final String ENHANCE_CLASS = "org.glassfish.jersey.server.ApplicationHandler";
38+
39+
private static final String HANDLE_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.jersey.v2.ApplicationHandlerInterceptor";
40+
41+
@Override
42+
protected ClassMatch enhanceClass() {
43+
return NameMatch.byName(ENHANCE_CLASS);
44+
}
45+
46+
@Override
47+
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
48+
return new ConstructorInterceptPoint[0];
49+
}
50+
51+
@Override
52+
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
53+
return new InstanceMethodsInterceptPoint[]{
54+
new InstanceMethodsInterceptPoint() {
55+
@Override
56+
public ElementMatcher<MethodDescription> getMethodsMatcher() {
57+
return named("handle");
58+
}
59+
60+
@Override
61+
public String getMethodsInterceptor() {
62+
return HANDLE_METHOD_INTERCEPTOR;
63+
}
64+
65+
@Override
66+
public boolean isOverrideArgs() {
67+
return false;
68+
}
69+
}
70+
};
71+
}
72+
73+
@Override
74+
protected List<WitnessMethod> witnessMethods() {
75+
return Collections.singletonList(new WitnessMethod(
76+
"org.glassfish.jersey.message.internal.InboundMessageContext",
77+
named("getHeaders").and(returns(named("javax.ws.rs.core.MultivaluedMap")))
78+
));
79+
}
80+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with 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+
jersey-2.x=org.apache.skywalking.apm.plugin.jersey.v2.define.ApplicationHandlerInstrumentation
18+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one or more
4+
~ contributor license agreements. See the NOTICE file distributed with
5+
~ this work for additional information regarding copyright ownership.
6+
~ The ASF licenses this file to You under the Apache License, Version 2.0
7+
~ (the "License"); you may not use this file except in compliance with
8+
~ the License. You may obtain a copy of the License at
9+
~
10+
~ http://www.apache.org/licenses/LICENSE-2.0
11+
~
12+
~ Unless required by applicable law or agreed to in writing, software
13+
~ distributed under the License is distributed on an "AS IS" BASIS,
14+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
~ See the License for the specific language governing permissions and
16+
~ limitations under the License.
17+
~
18+
-->
19+
20+
<project xmlns="http://maven.apache.org/POM/4.0.0"
21+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
23+
<parent>
24+
<artifactId>apm-sdk-plugin</artifactId>
25+
<groupId>org.apache.skywalking</groupId>
26+
<version>8.16.0-SNAPSHOT</version>
27+
</parent>
28+
<modelVersion>4.0.0</modelVersion>
29+
30+
<artifactId>apm-jersey-3.x-plugin</artifactId>
31+
32+
33+
<dependencies>
34+
<dependency>
35+
<groupId>org.glassfish.jersey.core</groupId>
36+
<artifactId>jersey-server</artifactId>
37+
<version>3.0.1</version>
38+
<scope>provided</scope>
39+
</dependency>
40+
</dependencies>
41+
42+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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.jersey.v3;
20+
21+
import java.lang.reflect.Method;
22+
import java.util.List;
23+
import java.util.Map;
24+
import org.apache.skywalking.apm.agent.core.context.CarrierItem;
25+
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
26+
import org.apache.skywalking.apm.agent.core.context.ContextManager;
27+
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
28+
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
29+
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
30+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
31+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
32+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
33+
import org.apache.skywalking.apm.agent.core.util.CollectionUtil;
34+
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
35+
import org.glassfish.jersey.server.ContainerRequest;
36+
37+
public class ApplicationHandlerInterceptor implements InstanceMethodsAroundInterceptor {
38+
39+
@Override
40+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
41+
MethodInterceptResult result) throws Throwable {
42+
ContainerRequest request = (ContainerRequest) allArguments[0];
43+
final ContextCarrier carrier = new ContextCarrier();
44+
CarrierItem items = carrier.items();
45+
while (items.hasNext()) {
46+
items = items.next();
47+
Map<String, List<String>> headerMap = request.getHeaders();
48+
List<String> values = headerMap.get(items.getHeadKey());
49+
if (!CollectionUtil.isEmpty(values)) {
50+
items.setHeadValue(values.get(0));
51+
}
52+
}
53+
String operationName = String.join(":", request.getMethod(), request.getPath(false));
54+
final AbstractSpan span = ContextManager.createEntrySpan(operationName, carrier);
55+
final String url = request.getRequestUri().toString();
56+
Tags.URL.set(span, url);
57+
Tags.HTTP.METHOD.set(span, request.getMethod());
58+
span.setComponent(ComponentsDefine.JERSEY);
59+
SpanLayer.asHttp(span);
60+
}
61+
62+
@Override
63+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
64+
Object ret) throws Throwable {
65+
ContextManager.stopSpan();
66+
return ret;
67+
}
68+
69+
@Override
70+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
71+
Class<?>[] argumentsTypes, Throwable t) {
72+
ContextManager.activeSpan().log(t);
73+
}
74+
}

0 commit comments

Comments
 (0)