Skip to content

Commit fab9ce5

Browse files
authored
Add skywaliking plugin for support Apache ShenYu (incubating) gateway (#8796) (#147)
1 parent 3c8e534 commit fab9ce5

File tree

35 files changed

+1845
-1
lines changed

35 files changed

+1845
-1
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ jobs:
9797
- undertow-worker-thread-pool-scenario
9898
- tomcat-thread-pool-scenario
9999
- guava-eventbus-scenario
100+
- shenyu-2.4.x-scenario
100101
steps:
101102
- uses: actions/checkout@v2
102103
with:

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,6 @@ public class ComponentsDefine {
220220
public static final OfficialComponent APACHE_KYLIN_JDBC_DRIVER = new OfficialComponent(121, "apache-kylin-jdbc-driver");
221221

222222
public static final OfficialComponent GUAVA_EVENT_BUS = new OfficialComponent(123, "GuavaEventBus");
223+
224+
public static final OfficialComponent APACHE_SHENYU = new OfficialComponent(127, "Apache-ShenYu");
223225
}

apm-sniffer/optional-plugins/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
<module>guava-cache-plugin</module>
5656
<module>fastjson-1.2.x-plugin</module>
5757
<module>jackson-2.x-plugin</module>
58+
<module>shenyu-2.4.x-plugin</module>
5859
</modules>
5960

6061
<dependencies>
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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>optional-plugins</artifactId>
25+
<groupId>org.apache.skywalking</groupId>
26+
<version>8.10.0-SNAPSHOT</version>
27+
</parent>
28+
<modelVersion>4.0.0</modelVersion>
29+
30+
<artifactId>apm-shenyu-2.4.x-plugin</artifactId>
31+
<name>shenyu-2.4.x-plugin</name>
32+
33+
<properties>
34+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
35+
<spring-webflux.version>5.0.0.RELEASE</spring-webflux.version>
36+
</properties>
37+
38+
39+
<dependencies>
40+
<dependency>
41+
<groupId>org.springframework</groupId>
42+
<artifactId>spring-webflux</artifactId>
43+
<version>${spring-webflux.version}</version>
44+
<scope>provided</scope>
45+
</dependency>
46+
<dependency>
47+
<groupId>org.apache.skywalking</groupId>
48+
<artifactId>apm-spring-webflux-5.x-plugin</artifactId>
49+
<version>${project.version}</version>
50+
</dependency>
51+
</dependencies>
52+
53+
<build>
54+
<plugins>
55+
<plugin>
56+
<groupId>org.apache.maven.plugins</groupId>
57+
<artifactId>maven-shade-plugin</artifactId>
58+
<version>3.2.4</version>
59+
<executions>
60+
<execution>
61+
<phase>package</phase>
62+
<goals>
63+
<goal>shade</goal>
64+
</goals>
65+
<configuration>
66+
<filters>
67+
<filter>
68+
<artifact>org.apache.skywalking:apm-spring-webflux-5.x-plugin</artifact>
69+
<excludes>
70+
<exclude>skywalking-plugin.def</exclude>
71+
</excludes>
72+
</filter>
73+
</filters>
74+
</configuration>
75+
</execution>
76+
</executions>
77+
</plugin>
78+
</plugins>
79+
</build>
80+
81+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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.shenyu.v24x;
20+
21+
import java.lang.reflect.Method;
22+
import java.util.List;
23+
import java.util.Objects;
24+
import java.util.Optional;
25+
26+
import org.apache.skywalking.apm.agent.core.context.CarrierItem;
27+
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
28+
import org.apache.skywalking.apm.agent.core.context.ContextManager;
29+
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
30+
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
31+
import org.apache.skywalking.apm.agent.core.context.tag.Tags.HTTP;
32+
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
33+
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
34+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
35+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
36+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
37+
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
38+
import org.springframework.http.HttpHeaders;
39+
import org.springframework.web.server.ServerWebExchange;
40+
import org.springframework.web.server.ServerWebExchangeDecorator;
41+
import org.springframework.web.server.adapter.DefaultServerWebExchange;
42+
43+
import reactor.core.publisher.Mono;
44+
45+
/**
46+
* Apache shenyu global-plugin interceptor.
47+
*/
48+
public class GlobalPluginExecuteMethodInterceptor implements InstanceMethodsAroundInterceptor {
49+
50+
public static final String SHENYU_AGENT_TRACE_ID = "shenyu-agent-trace-id";
51+
public static final String SKYWALKING_CONTEXT_SNAPSHOT = "SKYWALKING_CONTEXT_SNAPSHOT";
52+
public static final String SKYWALKING_SPAN = "SKYWALKING_SPAN";
53+
54+
@Override
55+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
56+
MethodInterceptResult result) throws Throwable {
57+
ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
58+
59+
ContextCarrier carrier = new ContextCarrier();
60+
CarrierItem next = carrier.items();
61+
HttpHeaders headers = exchange.getRequest().getHeaders();
62+
while (next.hasNext()) {
63+
next = next.next();
64+
List<String> header = headers.get(next.getHeadKey());
65+
if (header != null && header.size() > 0) {
66+
next.setHeadValue(header.get(0));
67+
}
68+
}
69+
70+
AbstractSpan span = ContextManager.createEntrySpan(exchange.getRequest().getURI().getPath(), carrier);
71+
span.setComponent(ComponentsDefine.APACHE_SHENYU);
72+
SpanLayer.asHttp(span);
73+
Tags.URL.set(span, exchange.getRequest().getURI().toString());
74+
HTTP.METHOD.set(span, exchange.getRequest().getMethodValue());
75+
76+
ContextSnapshot snapshot = ContextManager.capture();
77+
exchange.getAttributes().put(SHENYU_AGENT_TRACE_ID, snapshot.getTraceId().getId());
78+
EnhancedInstance instance = getInstance(allArguments[0]);
79+
instance.setSkyWalkingDynamicField(snapshot);
80+
span.prepareForAsync();
81+
ContextManager.stopSpan(span);
82+
83+
exchange.getAttributes().put(SKYWALKING_SPAN, span);
84+
}
85+
86+
@Override
87+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
88+
Object ret) throws Throwable {
89+
90+
ServerWebExchange exchange = (ServerWebExchange) allArguments[0];
91+
92+
AbstractSpan span = (AbstractSpan) exchange.getAttributes().get(SKYWALKING_SPAN);
93+
if (Objects.isNull(span)) {
94+
return ret;
95+
}
96+
Mono<Void> monoReturn = (Mono<Void>) ret;
97+
98+
// add skywalking context snapshot to reactor context. webclient plugin need to use SKYWALKING_CONTEXT_SNAPSHOT
99+
EnhancedInstance instance = getInstance(allArguments[0]);
100+
if (instance != null && instance.getSkyWalkingDynamicField() != null) {
101+
monoReturn = monoReturn.subscriberContext(
102+
c -> c.put(SKYWALKING_CONTEXT_SNAPSHOT, instance.getSkyWalkingDynamicField()));
103+
}
104+
105+
return monoReturn
106+
.doOnError(throwable -> span.errorOccurred().log(throwable))
107+
.doFinally(s -> {
108+
try {
109+
Optional.ofNullable(exchange.getResponse().getStatusCode()).ifPresent(httpStatus -> {
110+
Tags.HTTP_RESPONSE_STATUS_CODE.set(span, httpStatus.value());
111+
if (httpStatus.isError()) {
112+
span.errorOccurred();
113+
}
114+
});
115+
} finally {
116+
span.asyncFinish();
117+
}
118+
});
119+
}
120+
121+
@Override
122+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
123+
Class<?>[] argumentsTypes, Throwable t) {
124+
}
125+
126+
public static EnhancedInstance getInstance(Object o) {
127+
EnhancedInstance instance = null;
128+
if (o instanceof DefaultServerWebExchange) {
129+
instance = (EnhancedInstance) o;
130+
} else if (o instanceof ServerWebExchangeDecorator) {
131+
ServerWebExchange delegate = ((ServerWebExchangeDecorator) o).getDelegate();
132+
return getInstance(delegate);
133+
}
134+
return instance;
135+
}
136+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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.shenyu.v24x.define;
20+
21+
import static net.bytebuddy.matcher.ElementMatchers.named;
22+
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
23+
24+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
25+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
26+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
27+
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
28+
29+
import net.bytebuddy.description.method.MethodDescription;
30+
import net.bytebuddy.matcher.ElementMatcher;
31+
32+
/**
33+
* Apache shenyu global-plugin Instrumentation.
34+
*/
35+
public class GlobalPluginInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
36+
37+
private static final String ENHANCE_CLASS = "org.apache.shenyu.plugin.global.GlobalPlugin";
38+
39+
private static final String INTERCEPT_CLASS =
40+
"org.apache.skywalking.apm.plugin.shenyu.v24x.GlobalPluginExecuteMethodInterceptor";
41+
42+
@Override
43+
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
44+
return new ConstructorInterceptPoint[0];
45+
}
46+
47+
@Override
48+
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
49+
return new InstanceMethodsInterceptPoint[] {
50+
new InstanceMethodsInterceptPoint() {
51+
@Override
52+
public ElementMatcher<MethodDescription> getMethodsMatcher() {
53+
return named("execute");
54+
}
55+
56+
@Override
57+
public String getMethodsInterceptor() {
58+
return INTERCEPT_CLASS;
59+
}
60+
61+
@Override
62+
public boolean isOverrideArgs() {
63+
return false;
64+
}
65+
}
66+
};
67+
}
68+
69+
@Override
70+
protected ClassMatch enhanceClass() {
71+
return byName(ENHANCE_CLASS);
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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.shenyu.v24x.define;
20+
21+
22+
/**
23+
* Since all plugins have access to the ServerWebExchange and the plugins are processed in asynchronous threads,
24+
* we can put the snapshot into the enhanced ServerWebExchange object.
25+
*/
26+
public class ServerWebExchangeInstrumentation extends
27+
org.apache.skywalking.apm.plugin.spring.webflux.v5.define.ServerWebExchangeInstrumentation {
28+
29+
@Override
30+
protected String[] witnessClasses() {
31+
return new String[]{"org.apache.shenyu.plugin.global.GlobalPlugin"};
32+
}
33+
}
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+
shenyu-2.4.x=org.apache.skywalking.apm.plugin.shenyu.v24x.define.GlobalPluginInstrumentation
18+
shenyu-2.4.x=org.apache.skywalking.apm.plugin.shenyu.v24x.define.ServerWebExchangeInstrumentation

docs/en/setup/service-agent/java-agent/Optional-plugins.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ Now, we have the following known optional plugins.
1919
* Plugin of ehcache-2.x in the optional plugin folder. The reason for being an optional plugin is, this plugin enhanced cache framework, generates large number of local spans, which have a potential performance impact.
2020
* Plugin of guava-cache in the optional plugin folder. The reason for being an optional plugin is, this plugin enhanced cache framework, generates large number of local spans, which have a potential performance impact.
2121
* Plugin of fastjson serialization lib in optional plugin folder.
22-
* Plugin of jackson serialization lib in optional plugin folder.
22+
* Plugin of jackson serialization lib in optional plugin folder.
23+
* Plugin of Apache ShenYu(incubating) Gateway 2.4.x in optional plugin folder. Please only activate this plugin when you install agent in Apache ShenYu Gateway.

docs/en/setup/service-agent/java-agent/Plugin-list.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,4 @@
136136
- undertow-worker-thread-pool
137137
- tomcat-thread-pool
138138
- guava-eventbus
139+
- shenyu-2.4.x

0 commit comments

Comments
 (0)