Skip to content

Commit 0a1d7c2

Browse files
Fix Maven instrumentation for parallel builds (#5607)
1 parent b3510ca commit 0a1d7c2

File tree

8 files changed

+159
-15
lines changed

8 files changed

+159
-15
lines changed

dd-java-agent/instrumentation/maven-3.2.1/src/main/java/datadog/trace/instrumentation/maven3/MavenExecutionListener.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.Map;
1010
import org.apache.maven.execution.AbstractExecutionListener;
1111
import org.apache.maven.execution.ExecutionEvent;
12+
import org.apache.maven.execution.MavenExecutionRequest;
1213
import org.apache.maven.execution.MavenExecutionResult;
1314
import org.apache.maven.execution.MavenSession;
1415
import org.apache.maven.model.Plugin;
@@ -26,37 +27,39 @@ public class MavenExecutionListener extends AbstractExecutionListener {
2627
private static final String SYSTEM_PROPERTY_VARIABLES_CONFIG = "systemPropertyVariables";
2728
private static final String SYSTEM_PROPERTIES_CONFIG = "systemProperties";
2829

29-
private final BuildEventsHandler<MavenSession> buildEventsHandler;
30+
private final BuildEventsHandler<MavenExecutionRequest> buildEventsHandler;
3031

31-
public MavenExecutionListener(BuildEventsHandler<MavenSession> buildEventsHandler) {
32+
public MavenExecutionListener(BuildEventsHandler<MavenExecutionRequest> buildEventsHandler) {
3233
this.buildEventsHandler = buildEventsHandler;
3334
}
3435

3536
@Override
3637
public void sessionEnded(ExecutionEvent event) {
3738
MavenSession session = event.getSession();
39+
MavenExecutionRequest request = session.getRequest();
3840

3941
MavenExecutionResult result = session.getResult();
4042
if (result.hasExceptions()) {
4143
Throwable exception = MavenUtils.getException(result);
42-
buildEventsHandler.onTestSessionFail(session, exception);
44+
buildEventsHandler.onTestSessionFail(request, exception);
4345
}
4446

45-
buildEventsHandler.onTestSessionFinish(session);
47+
buildEventsHandler.onTestSessionFinish(request);
4648
}
4749

4850
@Override
4951
public void mojoSkipped(ExecutionEvent event) {
5052
MojoExecution mojoExecution = event.getMojoExecution();
5153
if (MavenUtils.isTestExecution(mojoExecution)) {
5254
MavenSession session = event.getSession();
55+
MavenExecutionRequest request = session.getRequest();
5356
MavenProject project = event.getProject();
5457
String projectName = project.getName();
5558
String lifecyclePhase = mojoExecution.getLifecyclePhase();
5659
String moduleName = projectName + " " + lifecyclePhase;
5760

5861
mojoStarted(event);
59-
buildEventsHandler.onTestModuleSkip(session, moduleName, null);
62+
buildEventsHandler.onTestModuleSkip(request, moduleName, null);
6063
mojoSucceeded(event);
6164
}
6265
}
@@ -66,6 +69,7 @@ public void mojoStarted(ExecutionEvent event) {
6669
MojoExecution mojoExecution = event.getMojoExecution();
6770
if (MavenUtils.isTestExecution(mojoExecution)) {
6871
MavenSession session = event.getSession();
72+
MavenExecutionRequest request = session.getRequest();
6973
MavenProject project = event.getProject();
7074
String projectName = project.getName();
7175
String lifecyclePhase = mojoExecution.getLifecyclePhase();
@@ -82,15 +86,15 @@ public void mojoStarted(ExecutionEvent event) {
8286
Collections.singletonMap(Tags.TEST_EXECUTION, executionId);
8387

8488
BuildEventsHandler.ModuleInfo moduleInfo =
85-
buildEventsHandler.onTestModuleStart(session, moduleName, startCommand, additionalTags);
89+
buildEventsHandler.onTestModuleStart(request, moduleName, startCommand, additionalTags);
8690

8791
Collection<MavenUtils.TestFramework> testFrameworks =
8892
MavenUtils.collectTestFrameworks(project);
8993
if (testFrameworks.size() == 1) {
9094
// if the module uses multiple test frameworks, we do not set the tags
9195
MavenUtils.TestFramework testFramework = testFrameworks.iterator().next();
9296
buildEventsHandler.onModuleTestFrameworkDetected(
93-
session, moduleName, testFramework.name, testFramework.version);
97+
request, moduleName, testFramework.name, testFramework.version);
9498
} else if (testFrameworks.size() > 1) {
9599
log.info(
96100
"Multiple test frameworks detected: {}. Test framework data will not be populated",
@@ -158,12 +162,13 @@ public void mojoSucceeded(ExecutionEvent event) {
158162
MojoExecution mojoExecution = event.getMojoExecution();
159163
if (MavenUtils.isTestExecution(mojoExecution)) {
160164
MavenSession session = event.getSession();
165+
MavenExecutionRequest request = session.getRequest();
161166
MavenProject project = event.getProject();
162167

163168
String projectName = project.getName();
164169
String lifecyclePhase = mojoExecution.getLifecyclePhase();
165170
String moduleName = projectName + " " + lifecyclePhase;
166-
buildEventsHandler.onTestModuleFinish(session, moduleName);
171+
buildEventsHandler.onTestModuleFinish(request, moduleName);
167172

168173
System.clearProperty(
169174
Strings.propertyNameToSystemPropertyName(CiVisibilityConfig.CIVISIBILITY_SESSION_ID));
@@ -177,15 +182,16 @@ public void mojoFailed(ExecutionEvent event) {
177182
MojoExecution mojoExecution = event.getMojoExecution();
178183
if (MavenUtils.isTestExecution(mojoExecution)) {
179184
MavenSession session = event.getSession();
185+
MavenExecutionRequest request = session.getRequest();
180186
MavenProject project = event.getProject();
181187

182188
String projectName = project.getName();
183189
String lifecyclePhase = mojoExecution.getLifecyclePhase();
184190
String moduleName = projectName + " " + lifecyclePhase;
185191

186192
Exception exception = event.getException();
187-
buildEventsHandler.onTestModuleFail(session, moduleName, exception);
188-
buildEventsHandler.onTestModuleFinish(session, moduleName);
193+
buildEventsHandler.onTestModuleFail(request, moduleName, exception);
194+
buildEventsHandler.onTestModuleFinish(request, moduleName);
189195

190196
System.clearProperty(
191197
Strings.propertyNameToSystemPropertyName(CiVisibilityConfig.CIVISIBILITY_SESSION_ID));

dd-java-agent/instrumentation/maven-3.2.1/src/main/java/datadog/trace/instrumentation/maven3/MavenLifecycleParticipant.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.concurrent.Future;
2828
import org.apache.maven.AbstractMavenLifecycleParticipant;
2929
import org.apache.maven.execution.ExecutionListener;
30+
import org.apache.maven.execution.MavenExecutionRequest;
3031
import org.apache.maven.execution.MavenSession;
3132
import org.apache.maven.lifecycle.MavenExecutionPlan;
3233
import org.apache.maven.lifecycle.internal.LifecycleExecutionPlanCalculator;
@@ -47,7 +48,7 @@ public class MavenLifecycleParticipant extends AbstractMavenLifecycleParticipant
4748

4849
private static final Logger LOGGER = LoggerFactory.getLogger(MavenLifecycleParticipant.class);
4950

50-
private final BuildEventsHandler<MavenSession> buildEventsHandler =
51+
private final BuildEventsHandler<MavenExecutionRequest> buildEventsHandler =
5152
InstrumentationBridge.createBuildEventsHandler();
5253

5354
@Override
@@ -88,18 +89,19 @@ public void afterProjectsRead(MavenSession session) {
8889
MavenProject rootProject = session.getTopLevelProject();
8990
Path projectRoot = rootProject.getBasedir().toPath();
9091

92+
MavenExecutionRequest request = session.getRequest();
9193
String projectName = rootProject.getName();
9294
String startCommand = MavenUtils.getCommandLine(session);
9395
String mavenVersion = MavenUtils.getMavenVersion(session);
9496
buildEventsHandler.onTestSessionStart(
95-
session, projectName, projectRoot, startCommand, "maven", mavenVersion);
97+
request, projectName, projectRoot, startCommand, "maven", mavenVersion);
9698

9799
Collection<MavenUtils.TestFramework> testFrameworks =
98100
MavenUtils.collectTestFrameworks(rootProject);
99101
if (testFrameworks.size() == 1) {
100102
MavenUtils.TestFramework testFramework = testFrameworks.iterator().next();
101103
buildEventsHandler.onTestFrameworkDetected(
102-
session, testFramework.name, testFramework.version);
104+
request, testFramework.name, testFramework.version);
103105
} else if (testFrameworks.size() > 1) {
104106
// if the module uses multiple test frameworks, we do not set the tags
105107
LOGGER.info(
@@ -299,8 +301,9 @@ private void configureTestExecutions(
299301

300302
private Void configureTestExecutions(
301303
MavenSession session, Path jvmExecutablePath, Collection<TestsExecution> testExecutions) {
304+
MavenExecutionRequest request = session.getRequest();
302305
ModuleExecutionSettings moduleExecutionSettings =
303-
buildEventsHandler.getModuleExecutionSettings(session, jvmExecutablePath);
306+
buildEventsHandler.getModuleExecutionSettings(request, jvmExecutablePath);
304307

305308
for (TestsExecution testExecution : testExecutions) {
306309
Path modulePath = testExecution.project.getBasedir().toPath();

dd-java-agent/instrumentation/maven-3.2.1/src/test/groovy/MavenTest.groovy

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import datadog.trace.civisibility.CiVisibilityTest
21
import datadog.trace.api.civisibility.CIConstants
32
import datadog.trace.api.config.CiVisibilityConfig
43
import datadog.trace.bootstrap.instrumentation.api.Tags
4+
import datadog.trace.civisibility.CiVisibilityTest
55
import org.apache.maven.cli.MavenCli
66
import org.apache.maven.lifecycle.LifecycleExecutionException
77
import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException
@@ -187,6 +187,42 @@ class MavenTest extends CiVisibilityTest {
187187
}
188188
}
189189

190+
def "test_maven_build_with_tests_in_multiple_modules_run_in_parallel_generates_spans"() {
191+
given:
192+
String[] args = ["-T4", "clean", "test"]
193+
String workingDirectory = projectFolder.toString()
194+
195+
when:
196+
def exitCode = new MavenCli().doMain(args, workingDirectory, null, null)
197+
198+
then:
199+
exitCode == 0
200+
201+
assertTraces(1) {
202+
trace(3, true) {
203+
def testSessionId = testSessionSpan(it, 2,
204+
"Maven Integration Tests Project",
205+
"mvn -T4 clean test",
206+
"maven:3.2.5",
207+
CIConstants.TEST_PASS)
208+
testModuleSpan(it, 0,
209+
CIConstants.TEST_PASS,
210+
[
211+
(Tags.TEST_COMMAND) : "mvn -T4 clean test",
212+
(Tags.TEST_EXECUTION): "maven-surefire-plugin:test:default-test",
213+
],
214+
null, testSessionId, "module-a test")
215+
testModuleSpan(it, 1,
216+
CIConstants.TEST_PASS,
217+
[
218+
(Tags.TEST_COMMAND) : "mvn -T4 clean test",
219+
(Tags.TEST_EXECUTION): "maven-surefire-plugin:test:default-test",
220+
],
221+
null, testSessionId, "module-b test")
222+
}
223+
}
224+
}
225+
190226
def "test_maven_build_with_unit_and_integration_tests_generates_spans"() {
191227
given:
192228
String[] args = ["verify"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0"?>
2+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.datadog.ci.test</groupId>
8+
<artifactId>maven-integration-test</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>maven-integration-test-module-a</artifactId>
13+
<version>1.0-SNAPSHOT</version>
14+
<name>module-a</name>
15+
16+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.example;
2+
3+
import static org.junit.Assert.assertTrue;
4+
5+
import org.junit.Test;
6+
7+
public class TestSucceed {
8+
9+
@Test
10+
public void test_succeed() {
11+
assertTrue(true);
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0"?>
2+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.datadog.ci.test</groupId>
8+
<artifactId>maven-integration-test</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>maven-integration-test-module-b</artifactId>
13+
<version>1.0-SNAPSHOT</version>
14+
<name>module-b</name>
15+
16+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.example;
2+
3+
import static org.junit.Assert.assertTrue;
4+
5+
import org.junit.Test;
6+
7+
public class TestSucceed {
8+
9+
@Test
10+
public void test_succeed() {
11+
assertTrue(true);
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4+
5+
<modelVersion>4.0.0</modelVersion>
6+
<groupId>com.datadog.ci.test</groupId>
7+
<artifactId>maven-integration-test</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
<packaging>pom</packaging>
10+
<name>Maven Integration Tests Project</name>
11+
12+
<modules>
13+
<module>module-a</module>
14+
<module>module-b</module>
15+
</modules>
16+
17+
<properties>
18+
<maven.compiler.source>8</maven.compiler.source>
19+
<maven.compiler.target>8</maven.compiler.target>
20+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
21+
</properties>
22+
23+
<dependencies>
24+
<dependency>
25+
<groupId>junit</groupId>
26+
<artifactId>junit</artifactId>
27+
<version>4.13.2</version>
28+
<scope>test</scope>
29+
</dependency>
30+
</dependencies>
31+
32+
<build>
33+
<plugins>
34+
<plugin>
35+
<groupId>org.apache.maven.plugins</groupId>
36+
<artifactId>maven-surefire-plugin</artifactId>
37+
</plugin>
38+
</plugins>
39+
</build>
40+
41+
</project>

0 commit comments

Comments
 (0)