Skip to content

Commit 35856b4

Browse files
authoredMar 9, 2025··
Add the virtual thread executor plugin (#751)
1 parent 534a80c commit 35856b4

File tree

22 files changed

+770
-1
lines changed

22 files changed

+770
-1
lines changed
 

‎.github/workflows/plugins-jdk21-test.0.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ jobs:
5656
matrix:
5757
case:
5858
- spring-6.x-scenario
59+
- jdk-virtual-thread-executor-scenario
5960
steps:
6061
- uses: actions/checkout@v2
6162
with:

‎CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Release Notes.
55
9.5.0
66
------------------
77

8+
* Add the virtual thread executor plugin
89

910

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

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

+2
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,6 @@ public class ComponentsDefine {
260260
public static final OfficialComponent SOLON_MVC = new OfficialComponent(158, "SolonMVC");
261261

262262
public static final OfficialComponent CAFFEINE = new OfficialComponent(160, "Caffeine");
263+
264+
public static final OfficialComponent THREAD_PER_TASK_EXECUTOR = new OfficialComponent(161, "ThreadPerTask-executor");
263265
}

‎apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/context/tag/Tags.java

+5
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,11 @@ public static final class HTTP {
155155
*/
156156
public static final StringTag THREAD_ID = new StringTag(23, "thread.id");
157157

158+
/**
159+
* THREAD_CARRIER represents the actual operating system thread that carries out the execution of the virtual thread.
160+
*/
161+
public static final StringTag THREAD_CARRIER = new StringTag(24, "thread.carrier");
162+
158163
/**
159164
* Creates a {@code StringTag} with the given key and cache it, if it's created before, simply return it without
160165
* creating a new one.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20+
<parent>
21+
<artifactId>bootstrap-plugins</artifactId>
22+
<groupId>org.apache.skywalking</groupId>
23+
<version>9.5.0-SNAPSHOT</version>
24+
</parent>
25+
<modelVersion>4.0.0</modelVersion>
26+
27+
<artifactId>apm-jdk-virtual-thread-executor-plugin</artifactId>
28+
<packaging>jar</packaging>
29+
30+
<name>apm-jdk-virtual-thread-executor-plugin</name>
31+
<url>http://maven.apache.org</url>
32+
33+
<properties>
34+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
35+
</properties>
36+
37+
38+
<build>
39+
<plugins>
40+
<plugin>
41+
<artifactId>maven-deploy-plugin</artifactId>
42+
</plugin>
43+
</plugins>
44+
</build>
45+
46+
</project>
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;
20+
21+
import org.apache.skywalking.apm.agent.core.context.ContextManager;
22+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
23+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
24+
25+
public class ThreadPerTaskExecutorConstructInterceptor implements InstanceConstructorInterceptor {
26+
27+
@Override
28+
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) throws Throwable {
29+
if (ContextManager.isActive()) {
30+
objInst.setSkyWalkingDynamicField(ContextManager.capture());
31+
}
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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;
20+
21+
import org.apache.skywalking.apm.agent.core.context.ContextManager;
22+
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
23+
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
24+
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
25+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
26+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
27+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
28+
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
29+
30+
import java.lang.reflect.Method;
31+
32+
public class ThreadPerTaskExecutorRunInterceptor implements InstanceMethodsAroundInterceptor {
33+
34+
@Override
35+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
36+
Object skyWalkingDynamicField = objInst.getSkyWalkingDynamicField();
37+
if (skyWalkingDynamicField == null) {
38+
return;
39+
}
40+
41+
if (!(skyWalkingDynamicField instanceof ContextSnapshot)) {
42+
return;
43+
}
44+
45+
AbstractSpan span = ContextManager.createLocalSpan(getOperationName(objInst, method));
46+
span.setComponent(ComponentsDefine.THREAD_PER_TASK_EXECUTOR);
47+
setCarrierThread(span);
48+
49+
ContextSnapshot contextSnapshot = (ContextSnapshot) skyWalkingDynamicField;
50+
ContextManager.continued(contextSnapshot);
51+
}
52+
53+
@Override
54+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
55+
if (ContextManager.isActive()) {
56+
ContextManager.stopSpan();
57+
}
58+
return ret;
59+
}
60+
61+
@Override
62+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
63+
if (ContextManager.isActive()) {
64+
ContextManager.activeSpan().log(t);
65+
}
66+
}
67+
68+
private String getOperationName(EnhancedInstance objInst, Method method) {
69+
return objInst.getClass().getName() + "." + method.getName();
70+
}
71+
72+
private void setCarrierThread(AbstractSpan span) {
73+
String threadInfo = Thread.currentThread().toString();
74+
if (threadInfo.startsWith("VirtualThread")) {
75+
String[] parts = threadInfo.split("@");
76+
if (parts.length >= 1) {
77+
Tags.THREAD_CARRIER.set(span, parts[1]);
78+
}
79+
}
80+
}
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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.define;
20+
21+
import net.bytebuddy.description.method.MethodDescription;
22+
import net.bytebuddy.matcher.ElementMatcher;
23+
import net.bytebuddy.matcher.ElementMatchers;
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+
import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch;
29+
30+
import static net.bytebuddy.matcher.ElementMatchers.any;
31+
32+
public class ThreadPerTaskExecutorFutureInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
33+
34+
private static final String ENHANCE_CLASS = "java.util.concurrent.ThreadPerTaskExecutor$ThreadBoundFuture";
35+
36+
private static final String INTERCEPT_RUN_METHOD = "run";
37+
38+
private static final String INTERCEPT_RUN_HANDLE = "org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorRunInterceptor";
39+
40+
private static final String TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorConstructInterceptor";
41+
42+
@Override
43+
public boolean isBootstrapInstrumentation() {
44+
return true;
45+
}
46+
47+
@Override
48+
protected ClassMatch enhanceClass() {
49+
return MultiClassNameMatch.byMultiClassMatch(ENHANCE_CLASS);
50+
}
51+
52+
@Override
53+
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
54+
return new ConstructorInterceptPoint[]{
55+
new ConstructorInterceptPoint() {
56+
@Override
57+
public ElementMatcher<MethodDescription> getConstructorMatcher() {
58+
return any();
59+
}
60+
61+
@Override
62+
public String getConstructorInterceptor() {
63+
return TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR;
64+
}
65+
}
66+
};
67+
}
68+
69+
@Override
70+
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
71+
return new InstanceMethodsInterceptPoint[]{
72+
new InstanceMethodsInterceptPoint() {
73+
@Override
74+
public ElementMatcher<MethodDescription> getMethodsMatcher() {
75+
return ElementMatchers.named(INTERCEPT_RUN_METHOD);
76+
}
77+
78+
@Override
79+
public String getMethodsInterceptor() {
80+
return INTERCEPT_RUN_HANDLE;
81+
}
82+
83+
@Override
84+
public boolean isOverrideArgs() {
85+
return true;
86+
}
87+
}
88+
};
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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.define;
20+
21+
import net.bytebuddy.description.method.MethodDescription;
22+
import net.bytebuddy.matcher.ElementMatcher;
23+
import net.bytebuddy.matcher.ElementMatchers;
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+
import org.apache.skywalking.apm.agent.core.plugin.match.MultiClassNameMatch;
29+
30+
import static net.bytebuddy.matcher.ElementMatchers.any;
31+
32+
public class ThreadPerTaskExecutorTaskRunnerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
33+
34+
private static final String ENHANCE_CLASS = "java.util.concurrent.ThreadPerTaskExecutor$TaskRunner";
35+
36+
private static final String INTERCEPT_RUN_METHOD = "run";
37+
38+
private static final String INTERCEPT_RUN_HANDLE = "org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorRunInterceptor";
39+
40+
private static final String TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.ThreadPerTaskExecutorConstructInterceptor";
41+
42+
@Override
43+
public boolean isBootstrapInstrumentation() {
44+
return true;
45+
}
46+
47+
@Override
48+
protected ClassMatch enhanceClass() {
49+
return MultiClassNameMatch.byMultiClassMatch(ENHANCE_CLASS);
50+
}
51+
52+
@Override
53+
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
54+
return new ConstructorInterceptPoint[]{
55+
new ConstructorInterceptPoint() {
56+
@Override
57+
public ElementMatcher<MethodDescription> getConstructorMatcher() {
58+
return any();
59+
}
60+
61+
@Override
62+
public String getConstructorInterceptor() {
63+
return TASK_RUNNER_CONSTRUCT_METHOD_INTERCEPTOR;
64+
}
65+
}
66+
};
67+
}
68+
69+
@Override
70+
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
71+
return new InstanceMethodsInterceptPoint[]{
72+
new InstanceMethodsInterceptPoint() {
73+
@Override
74+
public ElementMatcher<MethodDescription> getMethodsMatcher() {
75+
return ElementMatchers.named(INTERCEPT_RUN_METHOD);
76+
}
77+
78+
@Override
79+
public String getMethodsInterceptor() {
80+
return INTERCEPT_RUN_HANDLE;
81+
}
82+
83+
@Override
84+
public boolean isOverrideArgs() {
85+
return true;
86+
}
87+
}
88+
};
89+
}
90+
}
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+
jdk-virtual-thread-executor-plugin=org.apache.skywalking.apm.plugin.define.ThreadPerTaskExecutorTaskRunnerInstrumentation
18+
jdk-virtual-thread-executor-plugin=org.apache.skywalking.apm.plugin.define.ThreadPerTaskExecutorFutureInstrumentation

‎apm-sniffer/bootstrap-plugins/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
<module>jdk-threading-plugin</module>
4444
<module>jdk-threadpool-plugin</module>
4545
<module>jdk-forkjoinpool-plugin</module>
46+
<module>jdk-virtual-thread-executor-plugin</module>
4647
</modules>
4748

4849
<dependencies>

‎docs/en/setup/service-agent/java-agent/Application-toolkit-log4j-1.x.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
log4j.appender.CONSOLE.layout=org.apache.skywalking.apm.toolkit.log.log4j.v1.x.TraceIdPatternLayout
1515
```
1616

17-
* set `%T` in `layout.ConversionPattern` ( In 2.0-2016, you should use %x, [Why change?](https://github.com/wu-sheng/sky-walking/issues/77) )
17+
* set `%T` in `layout.ConversionPattern` ( In 2.0-2016, you should use %x, [Why change?](https://github.com/apache/skywalking/issues/77) )
1818
```properties
1919
log4j.appender.CONSOLE.layout.ConversionPattern=%d [%T] %-5p %c{1}:%L - %m%n
2020
```

‎docs/en/setup/service-agent/java-agent/Bootstrap-plugins.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Now, we have the following known bootstrap plugins.
77
* Plugin of JDK Callable and Runnable. Agent is compatible with JDK 1.8+
88
* Plugin of JDK ThreadPoolExecutor. Agent is compatible with JDK 1.8+
99
* Plugin of JDK ForkJoinPool. Agent is compatible with JDK 1.8+
10+
* Plugin of JDK VirtualThreadExecutor. Agent is compatible with JDK 21+
1011

1112
### HttpURLConnection Plugin Notice
1213
The plugin of JDK HttpURLConnection depended on `sun.net.*`. When using Java 9+, You should add some JVM options as follows:

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

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
- jackson-2.x
4949
- jdk-http-plugin
5050
- jdk-threading-plugin
51+
- jdk-virtual-thread-executor-plugin
5152
- jedis-2.x-3.x
5253
- jedis-4.x
5354
- jetty-client-9.0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
#
3+
# Licensed to the Apache Software Foundation (ASF) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The ASF licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
19+
home="$(cd "$(dirname $0)"; pwd)"
20+
21+
java -jar ${agent_opts} ${home}/../libs/jdk-virtual-thread-executor-scenario.jar &
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
segmentItems:
17+
- serviceName: jdk-virtual-thread-executor-scenario
18+
segmentSize: ge 0
19+
segments:
20+
- segmentId: not null
21+
spans:
22+
- operationName: GET:/case
23+
parentSpanId: -1
24+
spanId: 0
25+
spanLayer: Http
26+
startTime: not null
27+
endTime: not null
28+
componentId: 14
29+
isError: false
30+
spanType: Entry
31+
peer: ''
32+
skipAnalysis: false
33+
tags:
34+
- {key: url, value: 'http://localhost:8080/virtual-thread-executor-scenario/case'}
35+
- {key: http.method, value: GET}
36+
- {key: http.status_code, value: '200'}
37+
- segmentId: not null
38+
spans:
39+
- operationName: /apache/skywalking
40+
parentSpanId: 0
41+
spanId: 1
42+
spanLayer: Http
43+
startTime: nq 0
44+
endTime: nq 0
45+
componentId: 13
46+
isError: false
47+
spanType: Exit
48+
peer: github.com:443
49+
skipAnalysis: false
50+
tags:
51+
- {key: url, value: 'https://github.com/apache/skywalking'}
52+
- {key: http.method, value: GET}
53+
- {key: http.status_code, value: '200'}
54+
- operationName: java.util.concurrent.ThreadPerTaskExecutor$TaskRunner.run
55+
parentSpanId: -1
56+
spanId: 0
57+
startTime: nq 0
58+
endTime: nq 0
59+
componentId: 161
60+
isError: false
61+
spanType: Local
62+
skipAnalysis: false
63+
tags:
64+
- { key: thread.carrier, value: not null }
65+
refs:
66+
- { parentEndpoint: 'GET:/case', networkAddress: '', refType: CrossThread,
67+
parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not
68+
null, parentService: jdk-virtual-thread-executor-scenario, traceId: not null }
69+
70+
- segmentId: not null
71+
spans:
72+
- operationName: /apache/skywalking
73+
parentSpanId: 0
74+
spanId: 1
75+
spanLayer: Http
76+
startTime: nq 0
77+
endTime: nq 0
78+
componentId: 13
79+
isError: false
80+
spanType: Exit
81+
peer: github.com:443
82+
skipAnalysis: false
83+
tags:
84+
- { key: url, value: 'https://github.com/apache/skywalking' }
85+
- { key: http.method, value: GET }
86+
- { key: http.status_code, value: '200' }
87+
- operationName: java.util.concurrent.ThreadPerTaskExecutor$ThreadBoundFuture.run
88+
parentSpanId: -1
89+
spanId: 0
90+
startTime: nq 0
91+
endTime: nq 0
92+
componentId: 161
93+
isError: false
94+
spanType: Local
95+
skipAnalysis: false
96+
tags:
97+
- { key: thread.carrier, value: not null }
98+
refs:
99+
- { parentEndpoint: 'GET:/case', networkAddress: '', refType: CrossThread,
100+
parentSpanId: 0, parentTraceSegmentId: not null, parentServiceInstance: not
101+
null, parentService: jdk-virtual-thread-executor-scenario, traceId: not null }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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+
type: jvm
18+
entryService: http://localhost:8080/virtual-thread-executor-scenario/case
19+
healthCheck: http://localhost:8080/virtual-thread-executor-scenario/healthCheck
20+
runningMode: with_bootstrap
21+
withPlugins: apm-jdk-virtual-thread-executor-plugin-*.jar
22+
startScript: ./bin/startup.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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+
<project xmlns="http://maven.apache.org/POM/4.0.0"
19+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21+
<modelVersion>4.0.0</modelVersion>
22+
23+
<groupId>org.apache.skywalking</groupId>
24+
<artifactId>jdk-virtual-thread-executor-scenario</artifactId>
25+
<version>5.0.0</version>
26+
27+
<properties>
28+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
29+
<compiler.version>21</compiler.version>
30+
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
31+
<spring.boot.version>2.7.15</spring.boot.version>
32+
</properties>
33+
34+
<name>skywalking-jdk-virtual-thread-executor-scenario</name>
35+
36+
<dependencies>
37+
<dependency>
38+
<groupId>org.springframework.boot</groupId>
39+
<artifactId>spring-boot-starter-web</artifactId>
40+
<version>2.7.15</version>
41+
</dependency>
42+
43+
<dependency>
44+
<groupId>org.redisson</groupId>
45+
<artifactId>redisson</artifactId>
46+
<version>3.33.0</version>
47+
</dependency>
48+
</dependencies>
49+
50+
<build>
51+
<finalName>jdk-virtual-thread-executor-scenario</finalName>
52+
<plugins>
53+
<plugin>
54+
<groupId>org.springframework.boot</groupId>
55+
<artifactId>spring-boot-maven-plugin</artifactId>
56+
<version>${spring.boot.version}</version>
57+
<executions>
58+
<execution>
59+
<goals>
60+
<goal>repackage</goal>
61+
</goals>
62+
</execution>
63+
</executions>
64+
</plugin>
65+
<plugin>
66+
<artifactId>maven-compiler-plugin</artifactId>
67+
<version>${maven-compiler-plugin.version}</version>
68+
<configuration>
69+
<source>${compiler.version}</source>
70+
<target>${compiler.version}</target>
71+
<encoding>${project.build.sourceEncoding}</encoding>
72+
</configuration>
73+
</plugin>
74+
<plugin>
75+
<groupId>org.apache.maven.plugins</groupId>
76+
<artifactId>maven-assembly-plugin</artifactId>
77+
<executions>
78+
<execution>
79+
<id>assemble</id>
80+
<phase>package</phase>
81+
<goals>
82+
<goal>single</goal>
83+
</goals>
84+
<configuration>
85+
<descriptors>
86+
<descriptor>src/main/assembly/assembly.xml</descriptor>
87+
</descriptors>
88+
<outputDirectory>./target/</outputDirectory>
89+
</configuration>
90+
</execution>
91+
</executions>
92+
</plugin>
93+
<plugin>
94+
<groupId>org.apache.maven.plugins</groupId>
95+
<artifactId>maven-compiler-plugin</artifactId>
96+
<configuration>
97+
<source>21</source>
98+
<target>21</target>
99+
</configuration>
100+
</plugin>
101+
</plugins>
102+
</build>
103+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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+
<assembly
20+
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
21+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
23+
<formats>
24+
<format>zip</format>
25+
</formats>
26+
27+
<fileSets>
28+
<fileSet>
29+
<directory>./bin</directory>
30+
<fileMode>0775</fileMode>
31+
</fileSet>
32+
</fileSets>
33+
34+
<files>
35+
<file>
36+
<source>./target/jdk-virtual-thread-executor-scenario.jar</source>
37+
<outputDirectory>./libs</outputDirectory>
38+
<fileMode>0775</fileMode>
39+
</file>
40+
</files>
41+
</assembly>
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+
package test.apache.skywalking.apm.testcase.jdk.virtualThread;
19+
20+
import org.springframework.boot.SpringApplication;
21+
import org.springframework.boot.autoconfigure.SpringBootApplication;
22+
import org.springframework.context.annotation.Bean;
23+
import org.springframework.web.bind.annotation.GetMapping;
24+
import org.springframework.web.bind.annotation.RestController;
25+
import org.springframework.web.client.RestTemplate;
26+
27+
import java.util.concurrent.Callable;
28+
import java.util.concurrent.ExecutionException;
29+
import java.util.concurrent.ExecutorService;
30+
import java.util.concurrent.Executors;
31+
32+
@SpringBootApplication
33+
public class Application {
34+
35+
public static void main(String[] args) {
36+
SpringApplication.run(Application.class, args);
37+
}
38+
39+
@Bean
40+
public RestTemplate restTemplate() {
41+
return new RestTemplate();
42+
}
43+
44+
@RestController
45+
static class TestController {
46+
private final RestTemplate restTemplate;
47+
private final ExecutorService executorService;
48+
49+
public TestController(final RestTemplate restTemplate) {
50+
this.restTemplate = restTemplate;
51+
this.executorService = Executors.newVirtualThreadPerTaskExecutor();
52+
}
53+
54+
@GetMapping("/healthCheck")
55+
public String healthCheck() {
56+
return "Success";
57+
}
58+
59+
@GetMapping("/case")
60+
public String testCase() throws ExecutionException, InterruptedException {
61+
Runnable runnable = () -> restTemplate.getForEntity("https://github.com/apache/skywalking", String.class);
62+
executorService.execute(runnable);
63+
64+
Callable callable = () -> {
65+
restTemplate.getForEntity("https://github.com/apache/skywalking", String.class);
66+
return "success";
67+
};
68+
executorService.submit(callable).get();
69+
70+
return "success";
71+
}
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
server:
18+
port: 8080
19+
servlet:
20+
context-path: /virtual-thread-executor-scenario
21+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
all

0 commit comments

Comments
 (0)
Please sign in to comment.