Skip to content

Commit d851aa9

Browse files
nikita-tkachenko-datadogamarziali
authored andcommitted
Shutdown CI Visibility test event handlers before tracer (#8677)
1 parent 66f7b9f commit d851aa9

File tree

9 files changed

+49
-64
lines changed

9 files changed

+49
-64
lines changed

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

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import datadog.trace.api.civisibility.telemetry.NoOpMetricCollector;
1616
import datadog.trace.api.git.GitInfoProvider;
1717
import datadog.trace.bootstrap.ContextStore;
18+
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
1819
import datadog.trace.civisibility.config.ExecutionSettings;
1920
import datadog.trace.civisibility.config.JvmInfo;
2021
import datadog.trace.civisibility.coverage.file.instrumentation.CoverageClassTransformer;
@@ -41,6 +42,7 @@
4142
import java.nio.file.Path;
4243
import java.nio.file.Paths;
4344
import java.util.Collection;
45+
import java.util.concurrent.CopyOnWriteArrayList;
4446
import java.util.function.Predicate;
4547
import javax.annotation.Nullable;
4648
import org.slf4j.Logger;
@@ -101,10 +103,13 @@ public static void start(Instrumentation inst, SharedCommunicationObjects sco) {
101103

102104
CiVisibilityCoverageServices.Child coverageServices =
103105
new CiVisibilityCoverageServices.Child(services, repoServices, executionSettings);
104-
InstrumentationBridge.registerTestEventsHandlerFactory(
105-
new TestEventsHandlerFactory(
106-
services, repoServices, coverageServices, executionSettings));
106+
TestEventsHandlerFactory testEventsHandlerFactory =
107+
new TestEventsHandlerFactory(services, repoServices, coverageServices, executionSettings);
108+
InstrumentationBridge.registerTestEventsHandlerFactory(testEventsHandlerFactory);
107109
CoveragePerTestBridge.registerCoverageStoreRegistry(coverageServices.coverageStoreFactory);
110+
111+
AgentTracer.TracerAPI tracerAPI = AgentTracer.get();
112+
tracerAPI.addShutdownListener(testEventsHandlerFactory::shutdown);
108113
} else {
109114
InstrumentationBridge.registerTestEventsHandlerFactory(new NoOpTestEventsHandler.Factory());
110115
}
@@ -147,6 +152,8 @@ private static final class TestEventsHandlerFactory implements TestEventsHandler
147152
private final CiVisibilityRepoServices repoServices;
148153
private final TestFrameworkSession.Factory sessionFactory;
149154

155+
private final Collection<TestEventsHandler<?, ?>> handlers = new CopyOnWriteArrayList<>();
156+
150157
private TestEventsHandlerFactory(
151158
CiVisibilityServices services,
152159
CiVisibilityRepoServices repoServices,
@@ -174,12 +181,21 @@ public <SuiteKey, TestKey> TestEventsHandler<SuiteKey, TestKey> create(
174181
TestFrameworkSession testSession =
175182
sessionFactory.startSession(repoServices.moduleName, component, null, capabilities);
176183
TestFrameworkModule testModule = testSession.testModuleStart(repoServices.moduleName, null);
177-
return new TestEventsHandlerImpl<>(
178-
services.metricCollector,
179-
testSession,
180-
testModule,
181-
suiteStore != null ? suiteStore : new ConcurrentHashMapContextStore<>(),
182-
testStore != null ? testStore : new ConcurrentHashMapContextStore<>());
184+
TestEventsHandlerImpl<SuiteKey, TestKey> handler =
185+
new TestEventsHandlerImpl<>(
186+
services.metricCollector,
187+
testSession,
188+
testModule,
189+
suiteStore != null ? suiteStore : new ConcurrentHashMapContextStore<>(),
190+
testStore != null ? testStore : new ConcurrentHashMapContextStore<>());
191+
handlers.add(handler);
192+
return handler;
193+
}
194+
195+
public void shutdown() {
196+
for (TestEventsHandler<?, ?> handler : handlers) {
197+
handler.close();
198+
}
183199
}
184200
}
185201

dd-java-agent/instrumentation/junit-4.10/src/main/java/datadog/trace/instrumentation/junit4/TestEventsHandlerHolder.java

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import datadog.trace.api.civisibility.events.TestEventsHandler;
77
import datadog.trace.api.civisibility.events.TestSuiteDescriptor;
88
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
9-
import datadog.trace.util.AgentThreadFactory;
109
import datadog.trace.util.ConcurrentEnumMap;
1110
import java.util.Collection;
1211
import java.util.Map;
@@ -18,15 +17,6 @@ public abstract class TestEventsHandlerHolder {
1817
TestFrameworkInstrumentation, TestEventsHandler<TestSuiteDescriptor, TestDescriptor>>
1918
HANDLERS = new ConcurrentEnumMap<>(TestFrameworkInstrumentation.class);
2019

21-
static {
22-
Runtime.getRuntime()
23-
.addShutdownHook(
24-
AgentThreadFactory.newAgentThread(
25-
AgentThreadFactory.AgentThread.CI_TEST_EVENTS_SHUTDOWN_HOOK,
26-
TestEventsHandlerHolder::stop,
27-
false));
28-
}
29-
3020
public static synchronized void start(
3121
TestFrameworkInstrumentation framework, Collection<LibraryCapability> capabilities) {
3222
TestEventsHandler<TestSuiteDescriptor, TestDescriptor> handler = HANDLERS.get(framework);
@@ -38,13 +28,7 @@ public static synchronized void start(
3828
}
3929
}
4030

41-
public static synchronized void stop() {
42-
for (TestEventsHandler<TestSuiteDescriptor, TestDescriptor> handler : HANDLERS.values()) {
43-
handler.close();
44-
}
45-
HANDLERS.clear();
46-
}
47-
31+
/** Used by instrumentation tests */
4832
public static synchronized void stop(TestFrameworkInstrumentation framework) {
4933
TestEventsHandler<TestSuiteDescriptor, TestDescriptor> handler = HANDLERS.remove(framework);
5034
if (handler != null) {

dd-java-agent/instrumentation/junit-5.3/src/main/java/datadog/trace/instrumentation/junit5/TestEventsHandlerHolder.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import datadog.trace.api.civisibility.execution.TestExecutionHistory;
88
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
99
import datadog.trace.bootstrap.ContextStore;
10-
import datadog.trace.util.AgentThreadFactory;
1110
import datadog.trace.util.ConcurrentEnumMap;
1211
import java.util.Map;
1312
import org.junit.platform.engine.TestDescriptor;
@@ -23,15 +22,6 @@ public abstract class TestEventsHandlerHolder {
2322
private static volatile ContextStore<TestDescriptor, TestExecutionHistory>
2423
EXECUTION_HISTORY_STORE;
2524

26-
static {
27-
Runtime.getRuntime()
28-
.addShutdownHook(
29-
AgentThreadFactory.newAgentThread(
30-
AgentThreadFactory.AgentThread.CI_TEST_EVENTS_SHUTDOWN_HOOK,
31-
TestEventsHandlerHolder::stop,
32-
false));
33-
}
34-
3525
public static synchronized void setExecutionHistoryStore(
3626
ContextStore<TestDescriptor, TestExecutionHistory> executionHistoryStore) {
3727
if (EXECUTION_HISTORY_STORE == null) {
@@ -71,6 +61,7 @@ public static synchronized void start(
7161
}
7262
}
7363

64+
/** Used by instrumentation tests */
7465
public static synchronized void stop() {
7566
for (TestEventsHandler<TestDescriptor, TestDescriptor> handler : HANDLERS.values()) {
7667
handler.close();

dd-java-agent/instrumentation/karate/src/main/java/datadog/trace/instrumentation/karate/TestEventsHandlerHolder.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,13 @@
44
import datadog.trace.api.civisibility.events.TestDescriptor;
55
import datadog.trace.api.civisibility.events.TestEventsHandler;
66
import datadog.trace.api.civisibility.events.TestSuiteDescriptor;
7-
import datadog.trace.util.AgentThreadFactory;
87

98
public abstract class TestEventsHandlerHolder {
109

1110
public static volatile TestEventsHandler<TestSuiteDescriptor, TestDescriptor> TEST_EVENTS_HANDLER;
1211

1312
static {
1413
start();
15-
Runtime.getRuntime()
16-
.addShutdownHook(
17-
AgentThreadFactory.newAgentThread(
18-
AgentThreadFactory.AgentThread.CI_TEST_EVENTS_SHUTDOWN_HOOK,
19-
TestEventsHandlerHolder::stop,
20-
false));
2114
}
2215

2316
public static void start() {
@@ -26,6 +19,7 @@ public static void start() {
2619
"karate", null, null, KarateUtils.capabilities(KarateTracingHook.FRAMEWORK_VERSION));
2720
}
2821

22+
/** Used by instrumentation tests */
2923
public static void stop() {
3024
if (TEST_EVENTS_HANDLER != null) {
3125
TEST_EVENTS_HANDLER.close();

dd-java-agent/instrumentation/testng/src/main/java/datadog/trace/instrumentation/testng/TestEventsHandlerHolder.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import datadog.trace.api.civisibility.events.TestEventsHandler;
66
import datadog.trace.api.civisibility.events.TestSuiteDescriptor;
77
import datadog.trace.bootstrap.ContextStore;
8-
import datadog.trace.util.AgentThreadFactory;
98
import org.testng.ITestResult;
109

1110
public abstract class TestEventsHandlerHolder {
@@ -14,15 +13,6 @@ public abstract class TestEventsHandlerHolder {
1413

1514
private static ContextStore<ITestResult, DDTest> TEST_STORE;
1615

17-
static {
18-
Runtime.getRuntime()
19-
.addShutdownHook(
20-
AgentThreadFactory.newAgentThread(
21-
AgentThreadFactory.AgentThread.CI_TEST_EVENTS_SHUTDOWN_HOOK,
22-
TestEventsHandlerHolder::stop,
23-
false));
24-
}
25-
2616
public static synchronized void setContextStore(ContextStore<ITestResult, DDTest> testStore) {
2717
if (TEST_STORE == null) {
2818
TEST_STORE = testStore;
@@ -35,6 +25,7 @@ public static void start() {
3525
"testng", null, TEST_STORE, TestNGUtils.capabilities(TestNGUtils.getTestNGVersion()));
3626
}
3727

28+
/** Used by instrumentation tests */
3829
public static void stop() {
3930
if (TEST_EVENTS_HANDLER != null) {
4031
TEST_EVENTS_HANDLER.close();

dd-java-agent/instrumentation/weaver/src/main/java/datadog/trace/instrumentation/weaver/DatadogWeaverReporter.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import datadog.trace.api.civisibility.execution.TestExecutionHistory;
99
import datadog.trace.api.civisibility.telemetry.tag.TestFrameworkInstrumentation;
1010
import datadog.trace.api.time.SystemTimeSource;
11-
import datadog.trace.util.AgentThreadFactory;
1211
import java.lang.reflect.Method;
1312
import java.util.Collection;
1413
import java.util.Collections;
@@ -27,15 +26,6 @@ public class DatadogWeaverReporter {
2726
private static volatile TestEventsHandler<TestSuiteDescriptor, TestDescriptor>
2827
TEST_EVENTS_HANDLER;
2928

30-
static {
31-
Runtime.getRuntime()
32-
.addShutdownHook(
33-
AgentThreadFactory.newAgentThread(
34-
AgentThreadFactory.AgentThread.CI_TEST_EVENTS_SHUTDOWN_HOOK,
35-
DatadogWeaverReporter::stop,
36-
false));
37-
}
38-
3929
public static synchronized void start() {
4030
if (TEST_EVENTS_HANDLER == null) {
4131
TEST_EVENTS_HANDLER =
@@ -44,6 +34,7 @@ public static synchronized void start() {
4434
}
4535
}
4636

37+
/** Used by instrumentation tests */
4738
public static synchronized void stop() {
4839
if (TEST_EVENTS_HANDLER != null) {
4940
TEST_EVENTS_HANDLER.close();

dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
import java.util.ServiceLoader;
116116
import java.util.SortedSet;
117117
import java.util.concurrent.ConcurrentSkipListSet;
118+
import java.util.concurrent.CopyOnWriteArrayList;
118119
import java.util.concurrent.ExecutionException;
119120
import java.util.concurrent.TimeoutException;
120121
import java.util.zip.ZipOutputStream;
@@ -210,6 +211,7 @@ public static CoreTracerBuilder builder() {
210211
private final ProfilingContextIntegration profilingContextIntegration;
211212
private final boolean injectBaggageAsTags;
212213
private final boolean flushOnClose;
214+
private final Collection<Runnable> shutdownListeners = new CopyOnWriteArrayList<>();
213215

214216
/**
215217
* JVM shutdown callback, keeping a reference to it to remove this if DDTracer gets destroyed
@@ -1124,6 +1126,11 @@ public DataStreamsCheckpointer getDataStreamsCheckpointer() {
11241126
return this.dataStreamsMonitoring;
11251127
}
11261128

1129+
@Override
1130+
public void addShutdownListener(Runnable listener) {
1131+
this.shutdownListeners.add(listener);
1132+
}
1133+
11271134
@Override
11281135
public void addScopeListener(final ScopeListener listener) {
11291136
this.scopeManager.addScopeListener(listener);
@@ -1152,6 +1159,13 @@ public CallbackProvider getUniversalCallbackProvider() {
11521159

11531160
@Override
11541161
public void close() {
1162+
for (Runnable shutdownListener : shutdownListeners) {
1163+
try {
1164+
shutdownListener.run();
1165+
} catch (Exception e) {
1166+
log.error("Error while running shutdown listener", e);
1167+
}
1168+
}
11551169
if (flushOnClose) {
11561170
flush();
11571171
}

internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@ default SpanBuilder buildSpan(CharSequence spanName) {
412412
* @param serviceName The service name to use as default.
413413
*/
414414
void updatePreferredServiceName(String serviceName);
415+
416+
void addShutdownListener(Runnable listener);
415417
}
416418

417419
public interface SpanBuilder {
@@ -599,6 +601,9 @@ public DataStreamsCheckpointer getDataStreamsCheckpointer() {
599601
return getDataStreamsMonitoring();
600602
}
601603

604+
@Override
605+
public void addShutdownListener(Runnable listener) {}
606+
602607
@Override
603608
public void addScopeListener(final ScopeListener listener) {}
604609

internal-api/src/main/java/datadog/trace/util/AgentThreadFactory.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ public enum AgentThread {
5252
CI_SHELL_COMMAND("dd-ci-shell-command"),
5353
CI_GIT_DATA_UPLOADER("dd-ci-git-data-uploader"),
5454
CI_GIT_DATA_SHUTDOWN_HOOK("dd-ci-git-data-shutdown-hook"),
55-
CI_TEST_EVENTS_SHUTDOWN_HOOK("dd-ci-test-events-shutdown-hook"),
5655
CI_PROJECT_CONFIGURATOR("dd-ci-project-configurator"),
5756
CI_SIGNAL_SERVER("dd-ci-signal-server"),
5857

0 commit comments

Comments
 (0)