Skip to content

Commit 5a939c0

Browse files
Propagate module context from build system process to child JVM processes (#7710)
1 parent 919bf01 commit 5a939c0

File tree

44 files changed

+305
-288
lines changed

Some content is hidden

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

44 files changed

+305
-288
lines changed

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityRepoServices.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import datadog.trace.civisibility.source.SourcePathResolver;
3232
import datadog.trace.civisibility.source.index.RepoIndexProvider;
3333
import datadog.trace.civisibility.source.index.RepoIndexSourcePathResolver;
34-
import datadog.trace.civisibility.utils.ProcessHierarchyUtils;
3534
import java.nio.file.Path;
3635
import java.nio.file.Paths;
3736
import java.util.Map;
@@ -76,11 +75,12 @@ public class CiVisibilityRepoServices {
7675
codeowners = buildCodeowners(repoRoot);
7776
sourcePathResolver = buildSourcePathResolver(repoRoot, repoIndexProvider);
7877

79-
if (ProcessHierarchyUtils.isChild()) {
78+
if (services.processHierarchy.isChild()) {
8079
executionSettingsFactory = buildExecutionSettingsFetcher(services.signalClientFactory);
8180
} else {
8281
executionSettingsFactory =
8382
buildExecutionSettingsFactory(
83+
services.processHierarchy,
8484
services.config,
8585
services.metricCollector,
8686
services.backendApi,
@@ -122,6 +122,7 @@ private static ExecutionSettingsFactory buildExecutionSettingsFetcher(
122122
}
123123

124124
private static ExecutionSettingsFactory buildExecutionSettingsFactory(
125+
ProcessHierarchy processHierarchy,
125126
Config config,
126127
CiVisibilityMetricCollector metricCollector,
127128
BackendApi backendApi,
@@ -138,7 +139,7 @@ private static ExecutionSettingsFactory buildExecutionSettingsFactory(
138139

139140
ExecutionSettingsFactoryImpl factory =
140141
new ExecutionSettingsFactoryImpl(config, configurationApi, gitDataUploader, repoRoot);
141-
if (ProcessHierarchyUtils.isHeadless()) {
142+
if (processHierarchy.isHeadless()) {
142143
return factory;
143144
} else {
144145
return new MultiModuleExecutionSettingsFactory(config, factory);

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilityServices.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import datadog.trace.civisibility.source.CompilerAidedMethodLinesResolver;
2929
import datadog.trace.civisibility.source.MethodLinesResolver;
3030
import datadog.trace.civisibility.source.index.*;
31-
import datadog.trace.civisibility.utils.ProcessHierarchyUtils;
3231
import java.lang.reflect.Type;
3332
import java.net.InetSocketAddress;
3433
import java.nio.file.FileSystem;
@@ -56,6 +55,7 @@ public class CiVisibilityServices {
5655

5756
static final String DD_ENV_VARS_PROVIDER_KEY_HEADER = "DD-Env-Vars-Provider-Key";
5857

58+
final ProcessHierarchy processHierarchy;
5959
final Config config;
6060
final CiVisibilityMetricCollector metricCollector;
6161
final BackendApi backendApi;
@@ -72,6 +72,7 @@ public class CiVisibilityServices {
7272
CiVisibilityMetricCollector metricCollector,
7373
SharedCommunicationObjects sco,
7474
GitInfoProvider gitInfoProvider) {
75+
this.processHierarchy = new ProcessHierarchy();
7576
this.config = config;
7677
this.metricCollector = metricCollector;
7778
this.backendApi =
@@ -91,8 +92,8 @@ public class CiVisibilityServices {
9192
new CILocalGitInfoBuilder(gitClientFactory, GIT_FOLDER_NAME));
9293
gitInfoProvider.registerGitInfoBuilder(new GitClientGitInfoBuilder(config, gitClientFactory));
9394

94-
if (ProcessHierarchyUtils.isChild()) {
95-
InetSocketAddress signalServerAddress = ProcessHierarchyUtils.getSignalServerAddress();
95+
if (processHierarchy.isChild()) {
96+
InetSocketAddress signalServerAddress = processHierarchy.getSignalServerAddress();
9697
this.signalClientFactory = new SignalClient.Factory(signalServerAddress, config);
9798

9899
RepoIndexProvider indexFetcher = new RepoIndexFetcher(signalClientFactory);

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/CiVisibilitySystem.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import datadog.trace.civisibility.telemetry.CiVisibilityMetricCollectorImpl;
3434
import datadog.trace.civisibility.test.ExecutionStrategy;
3535
import datadog.trace.civisibility.utils.ConcurrentHashMapContextStore;
36-
import datadog.trace.civisibility.utils.ProcessHierarchyUtils;
3736
import datadog.trace.util.throwable.FatalAgentMisconfigurationError;
3837
import java.lang.instrument.Instrumentation;
3938
import java.nio.file.Path;
@@ -79,7 +78,7 @@ public static void start(Instrumentation inst, SharedCommunicationObjects sco) {
7978
InstrumentationBridge.registerBuildEventsHandlerFactory(buildEventsHandlerFactory(services));
8079
CIVisibility.registerSessionFactory(manualApiSessionFactory(services));
8180

82-
if (ProcessHierarchyUtils.isChild() || ProcessHierarchyUtils.isHeadless()) {
81+
if (services.processHierarchy.isChild() || services.processHierarchy.isHeadless()) {
8382
CiVisibilityRepoServices repoServices = services.repoServices(getCurrentPath());
8483

8584
ExecutionSettings executionSettings =
@@ -142,7 +141,7 @@ private TestEventsHandlerFactory(
142141
ExecutionSettings executionSettings) {
143142
this.services = services;
144143
this.repoServices = repoServices;
145-
if (ProcessHierarchyUtils.isChild()) {
144+
if (services.processHierarchy.isChild()) {
146145
sessionFactory =
147146
childTestFrameworkSessionFactory(
148147
services, repoServices, coverageServices, executionSettings);
@@ -222,19 +221,16 @@ private static TestFrameworkSession.Factory childTestFrameworkSessionFactory(
222221
CiVisibilityCoverageServices.Child coverageServices,
223222
ExecutionSettings executionSettings) {
224223
return (String projectName, String component, Long startTime) -> {
225-
long parentProcessSessionId = ProcessHierarchyUtils.getParentSessionId();
226-
long parentProcessModuleId = ProcessHierarchyUtils.getParentModuleId();
227-
228224
String sessionName = services.config.getCiVisibilitySessionName();
229225
String testCommand = services.config.getCiVisibilityTestCommand();
230226
TestDecorator testDecorator =
231227
new TestDecoratorImpl(component, sessionName, testCommand, repoServices.ciTags);
232228

233229
ExecutionStrategy executionStrategy =
234230
new ExecutionStrategy(services.config, executionSettings);
231+
235232
return new ProxyTestSession(
236-
parentProcessSessionId,
237-
parentProcessModuleId,
233+
services.processHierarchy.parentProcessModuleContext,
238234
services.config,
239235
services.metricCollector,
240236
testDecorator,
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package datadog.trace.civisibility;
2+
3+
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.propagate;
4+
5+
import datadog.trace.api.config.CiVisibilityConfig;
6+
import datadog.trace.bootstrap.instrumentation.api.AgentPropagation;
7+
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
8+
import datadog.trace.util.Strings;
9+
import java.net.InetSocketAddress;
10+
import java.util.Properties;
11+
import javax.annotation.Nullable;
12+
13+
public class ProcessHierarchy {
14+
15+
private static final class SystemPropertiesPropagationGetter
16+
implements AgentPropagation.ContextVisitor<Properties> {
17+
static final AgentPropagation.ContextVisitor<Properties> INSTANCE =
18+
new SystemPropertiesPropagationGetter();
19+
20+
private SystemPropertiesPropagationGetter() {}
21+
22+
@Override
23+
public void forEachKey(Properties carrier, AgentPropagation.KeyClassifier classifier) {
24+
for (String propertyName : carrier.stringPropertyNames()) {
25+
if (!classifier.accept(propertyName, carrier.getProperty(propertyName))) {
26+
return;
27+
}
28+
}
29+
}
30+
}
31+
32+
@Nullable public final AgentSpan.Context.Extracted parentProcessModuleContext;
33+
34+
ProcessHierarchy() {
35+
parentProcessModuleContext =
36+
propagate().extract(System.getProperties(), SystemPropertiesPropagationGetter.INSTANCE);
37+
}
38+
39+
/**
40+
* Module span context is propagated from the parent process if it runs with the tracer attached.
41+
* If module span context is note there, either we are in the build system, or we are in the tests
42+
* JVM and the build system is not instrumented.
43+
*/
44+
public boolean isChild() {
45+
return parentProcessModuleContext != null;
46+
}
47+
48+
/**
49+
* Determines if current process runs in "headless mode", i.e. has no instrumented parent and is
50+
* not one of the supported build system processes.
51+
*/
52+
public boolean isHeadless() {
53+
return !isChild() && !isParent();
54+
}
55+
56+
private boolean isParent() {
57+
return isMavenParent() || isGradleDaemon();
58+
}
59+
60+
private boolean isMavenParent() {
61+
return System.getProperty("maven.home") != null
62+
&& System.getProperty("classworlds.conf") != null;
63+
}
64+
65+
private boolean isGradleDaemon() {
66+
return ClassLoader.getSystemClassLoader()
67+
.getResource("org/gradle/launcher/daemon/bootstrap/GradleDaemon.class")
68+
!= null
69+
// double-check this is not a Gradle Worker
70+
&& System.getProperties().getProperty("org.gradle.internal.worker.tmpdir") == null;
71+
}
72+
73+
@Nullable
74+
public InetSocketAddress getSignalServerAddress() {
75+
// System.getProperty is used rather than Config,
76+
// because system variables can be set after config was initialized
77+
String host =
78+
System.getProperty(
79+
Strings.propertyNameToSystemPropertyName(
80+
CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_HOST));
81+
String port =
82+
System.getProperty(
83+
Strings.propertyNameToSystemPropertyName(
84+
CiVisibilityConfig.CIVISIBILITY_SIGNAL_SERVER_PORT));
85+
if (host != null && port != null) {
86+
return new InetSocketAddress(host, Integer.parseInt(port));
87+
} else {
88+
return null;
89+
}
90+
}
91+
}

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/ConcurrentCoverageStore.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package datadog.trace.civisibility.coverage;
22

3+
import datadog.trace.api.DDTraceId;
34
import datadog.trace.api.civisibility.coverage.CoverageProbes;
45
import datadog.trace.api.civisibility.coverage.CoverageStore;
56
import datadog.trace.api.civisibility.coverage.TestReport;
@@ -34,14 +35,14 @@ private T create(Thread thread) {
3435
}
3536

3637
@Override
37-
public boolean report(Long testSessionId, Long testSuiteId, long testSpanId) {
38+
public boolean report(DDTraceId testSessionId, Long testSuiteId, long testSpanId) {
3839
report = report(testSessionId, testSuiteId, testSpanId, probes.values());
3940
return report != null && report.isNotEmpty();
4041
}
4142

4243
@Nullable
4344
protected abstract TestReport report(
44-
Long testSessionId, Long testSuiteId, long testSpanId, Collection<T> probes);
45+
DDTraceId testSessionId, Long testSuiteId, long testSpanId, Collection<T> probes);
4546

4647
@Nullable
4748
@Override

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/file/FileCoverageStore.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package datadog.trace.civisibility.coverage.file;
22

3+
import datadog.trace.api.DDTraceId;
34
import datadog.trace.api.civisibility.config.TestIdentifier;
45
import datadog.trace.api.civisibility.coverage.CoverageStore;
56
import datadog.trace.api.civisibility.coverage.TestReport;
@@ -45,7 +46,7 @@ private FileCoverageStore(
4546
@Nullable
4647
@Override
4748
protected TestReport report(
48-
Long testSessionId, Long testSuiteId, long testSpanId, Collection<FileProbes> probes) {
49+
DDTraceId testSessionId, Long testSuiteId, long testSpanId, Collection<FileProbes> probes) {
4950
try {
5051
Set<Class<?>> combinedClasses = Collections.newSetFromMap(new IdentityHashMap<>());
5152
Collection<String> combinedNonCodeResources = new HashSet<>();

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/line/LineCoverageStore.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package datadog.trace.civisibility.coverage.line;
22

3+
import datadog.trace.api.DDTraceId;
34
import datadog.trace.api.civisibility.config.TestIdentifier;
45
import datadog.trace.api.civisibility.coverage.CoverageStore;
56
import datadog.trace.api.civisibility.coverage.TestReport;
@@ -51,7 +52,7 @@ private LineCoverageStore(
5152
@Nullable
5253
@Override
5354
protected TestReport report(
54-
Long testSessionId, Long testSuiteId, long testSpanId, Collection<LineProbes> probes) {
55+
DDTraceId testSessionId, Long testSuiteId, long testSpanId, Collection<LineProbes> probes) {
5556
try {
5657
Map<Class<?>, ExecutionDataAdapter> combinedExecutionData = new IdentityHashMap<>();
5758
Collection<String> combinedNonCodeResources = new HashSet<>();

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/percentage/child/ChildProcessCoverageReporter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package datadog.trace.civisibility.coverage.percentage.child;
22

3+
import datadog.trace.api.DDTraceId;
34
import datadog.trace.civisibility.ipc.ModuleSignal;
45
import javax.annotation.Nullable;
56

@@ -12,5 +13,5 @@
1213
*/
1314
public interface ChildProcessCoverageReporter {
1415
@Nullable
15-
ModuleSignal createCoverageSignal(long sessionId, long moduleId);
16+
ModuleSignal createCoverageSignal(DDTraceId sessionId, long moduleId);
1617
}

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/coverage/percentage/child/JacocoChildProcessCoverageReporter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package datadog.trace.civisibility.coverage.percentage.child;
22

3+
import datadog.trace.api.DDTraceId;
34
import datadog.trace.civisibility.ipc.ModuleCoverageDataJacoco;
45
import datadog.trace.civisibility.ipc.ModuleSignal;
56
import java.util.function.Supplier;
@@ -15,7 +16,7 @@ public JacocoChildProcessCoverageReporter(Supplier<byte[]> coverageDataSupplier)
1516

1617
@Nullable
1718
@Override
18-
public ModuleSignal createCoverageSignal(long sessionId, long moduleId) {
19+
public ModuleSignal createCoverageSignal(DDTraceId sessionId, long moduleId) {
1920
byte[] coverageData = coverageDataSupplier.get();
2021
if (coverageData != null) {
2122
return new ModuleCoverageDataJacoco(sessionId, moduleId, coverageData);

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestModule.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
public abstract class AbstractTestModule {
2020

2121
protected final AgentSpan span;
22-
protected final long sessionId;
2322
protected final String moduleName;
2423
protected final Config config;
2524
protected final CiVisibilityMetricCollector metricCollector;
@@ -31,7 +30,6 @@ public abstract class AbstractTestModule {
3130

3231
public AbstractTestModule(
3332
AgentSpan.Context sessionSpanContext,
34-
long sessionId,
3533
String moduleName,
3634
@Nullable Long startTime,
3735
InstrumentationType instrumentationType,
@@ -42,7 +40,6 @@ public AbstractTestModule(
4240
Codeowners codeowners,
4341
MethodLinesResolver methodLinesResolver,
4442
Consumer<AgentSpan> onSpanFinish) {
45-
this.sessionId = sessionId;
4643
this.moduleName = moduleName;
4744
this.config = config;
4845
this.metricCollector = metricCollector;
@@ -65,7 +62,7 @@ public AbstractTestModule(
6562
span.setTag(Tags.TEST_MODULE, moduleName);
6663

6764
span.setTag(Tags.TEST_MODULE_ID, span.getSpanId());
68-
span.setTag(Tags.TEST_SESSION_ID, sessionId);
65+
span.setTag(Tags.TEST_SESSION_ID, span.getTraceId());
6966

7067
// setting status to skip initially,
7168
// as we do not know in advance whether the module will have any children

0 commit comments

Comments
 (0)