Skip to content

Commit d3ed23d

Browse files
committed
WIP
1 parent 13d1c4b commit d3ed23d

File tree

7 files changed

+85
-36
lines changed

7 files changed

+85
-36
lines changed

communication/src/main/java/datadog/communication/ddagent/SharedCommunicationObjects.java

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import datadog.remoteconfig.DefaultConfigurationPoller;
1212
import datadog.trace.api.Config;
1313
import datadog.trace.util.AgentTaskScheduler;
14+
import java.util.ArrayList;
15+
import java.util.List;
1416
import java.util.concurrent.TimeUnit;
1517
import java.util.function.Supplier;
1618
import okhttp3.HttpUrl;
@@ -21,12 +23,23 @@
2123
public class SharedCommunicationObjects {
2224
private static final Logger log = LoggerFactory.getLogger(SharedCommunicationObjects.class);
2325

26+
private final List<Runnable> pausedComponents = new ArrayList<>();
27+
private volatile boolean paused;
28+
2429
public OkHttpClient okHttpClient;
2530
public HttpUrl agentUrl;
2631
public Monitoring monitoring;
2732
private DDAgentFeaturesDiscovery featuresDiscovery;
2833
private ConfigurationPoller configurationPoller;
2934

35+
public SharedCommunicationObjects() {
36+
this(false);
37+
}
38+
39+
public SharedCommunicationObjects(boolean paused) {
40+
this.paused = paused;
41+
}
42+
3043
public void createRemaining(Config config) {
3144
if (monitoring == null) {
3245
monitoring = Monitoring.DISABLED;
@@ -46,6 +59,30 @@ public void createRemaining(Config config) {
4659
}
4760
}
4861

62+
public void whenReady(Runnable callback) {
63+
synchronized (pausedComponents) {
64+
if (paused) {
65+
pausedComponents.add(callback);
66+
} else {
67+
callback.run();
68+
}
69+
}
70+
}
71+
72+
public void resume() {
73+
paused = false;
74+
synchronized (pausedComponents) {
75+
for (Runnable callback : pausedComponents) {
76+
try {
77+
callback.run();
78+
} catch (Throwable e) {
79+
log.warn("Problem resuming remote component {}", callback, e);
80+
}
81+
}
82+
pausedComponents.clear();
83+
}
84+
}
85+
4986
private static HttpUrl parseAgentUrl(Config config) {
5087
String agentUrl = config.getAgentUrl();
5188
if (agentUrl.startsWith("unix:")) {
@@ -100,11 +137,14 @@ public DDAgentFeaturesDiscovery featuresDiscovery(Config config) {
100137
agentUrl,
101138
config.isTraceAgentV05Enabled(),
102139
config.isTracerMetricsEnabled());
103-
if (AGENT_THREAD_GROUP.equals(Thread.currentThread().getThreadGroup())) {
104-
featuresDiscovery.discover(); // safe to run on same thread
105-
} else {
106-
// avoid performing blocking I/O operation on application thread
107-
AgentTaskScheduler.INSTANCE.execute(featuresDiscovery::discover);
140+
141+
if (!paused) {
142+
if (AGENT_THREAD_GROUP.equals(Thread.currentThread().getThreadGroup())) {
143+
featuresDiscovery.discover(); // safe to run on same thread
144+
} else {
145+
// avoid performing blocking I/O operation on application thread
146+
AgentTaskScheduler.INSTANCE.execute(featuresDiscovery::discover);
147+
}
108148
}
109149
}
110150
return featuresDiscovery;

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/Agent.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ public void run() {
347347
* logging facility. Likewise on IBM JDKs OkHttp may indirectly load 'IBMSASL' which in turn loads LogManager.
348348
*/
349349
InstallDatadogTracerCallback installDatadogTracerCallback =
350-
new InstallDatadogTracerCallback(initTelemetry, inst);
350+
new InstallDatadogTracerCallback(initTelemetry, inst, delayOkHttp);
351351
if (delayOkHttp) {
352352
log.debug("Custom logger detected. Delaying Datadog Tracer initialization.");
353353
registerLogManagerCallback(installDatadogTracerCallback);
@@ -496,26 +496,30 @@ public void execute() {
496496
}
497497

498498
protected static class InstallDatadogTracerCallback extends ClassLoadCallBack {
499-
private final InitializationTelemetry initTelemetry;
500499
private final Instrumentation instrumentation;
501500
private final Object sco;
502501
private final Class<?> scoClass;
502+
private final boolean delayOkHttp;
503503

504504
public InstallDatadogTracerCallback(
505-
InitializationTelemetry initTelemetry, Instrumentation instrumentation) {
506-
this.initTelemetry = initTelemetry;
505+
InitializationTelemetry initTelemetry,
506+
Instrumentation instrumentation,
507+
boolean delayOkHttp) {
508+
this.delayOkHttp = delayOkHttp;
507509
this.instrumentation = instrumentation;
508510
try {
509511
scoClass =
510512
AGENT_CLASSLOADER.loadClass("datadog.communication.ddagent.SharedCommunicationObjects");
511-
sco = scoClass.getConstructor().newInstance();
513+
sco = scoClass.getConstructor(boolean.class).newInstance(delayOkHttp);
512514
} catch (ClassNotFoundException
513515
| NoSuchMethodException
514516
| InstantiationException
515517
| IllegalAccessException
516518
| InvocationTargetException e) {
517519
throw new UndeclaredThrowableException(e);
518520
}
521+
522+
installDatadogTracer(initTelemetry, scoClass, sco);
519523
}
520524

521525
@Override
@@ -525,7 +529,10 @@ public AgentThread agentThread() {
525529

526530
@Override
527531
public void execute() {
528-
installDatadogTracer(initTelemetry, scoClass, sco);
532+
if (delayOkHttp) {
533+
resumeRemoteComponents();
534+
}
535+
529536
maybeStartAppSec(scoClass, sco);
530537
maybeStartIast(instrumentation, scoClass, sco);
531538
maybeStartCiVisibility(instrumentation, scoClass, sco);
@@ -538,6 +545,16 @@ public void execute() {
538545
startTelemetry(instrumentation, scoClass, sco);
539546
}
540547
}
548+
549+
private void resumeRemoteComponents() {
550+
try {
551+
Thread.sleep(500);
552+
scoClass.getMethod("resume").invoke(sco);
553+
} catch (InterruptedException ignore) {
554+
} catch (Exception e) {
555+
log.error("Error resuming remote components", e);
556+
}
557+
}
541558
}
542559

543560
protected static class StartProfilingAgentCallback extends ClassLoadCallBack {

dd-java-agent/src/test/groovy/datadog/trace/agent/CustomLogManagerTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class CustomLogManagerTest extends Specification {
2727
, true) == 0
2828
}
2929

30-
def "agent services starts up in premain if configured log manager on system classpath"() {
30+
def "agent services startup is delayed even if configured log manager on system classpath"() {
3131
expect:
3232
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
3333
, [

dd-java-agent/src/test/groovy/datadog/trace/agent/CustomMBeanServerBuilderTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class CustomMBeanServerBuilderTest extends Specification {
2828
, true) == 0
2929
}
3030

31-
def "JMXFetch starts up in premain if configured MBeanServerBuilder on system classpath"() {
31+
def "JMXFetch startup is delayed even if configured MBeanServerBuilder on system classpath"() {
3232
expect:
3333
IntegrationTestUtils.runOnSeparateJvm(MBeanServerBuilderSetter.getName()
3434
, [

dd-java-agent/src/test/java/jvmbootstraptest/LogManagerSetter.java

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ public static void main(final String... args) throws Exception {
3939
} else if (System.getProperty("java.util.logging.manager") != null) {
4040
System.out.println("java.util.logging.manager != null");
4141

42-
assertTraceInstallationDelayed(
43-
"tracer install must be delayed when log manager system property is present.");
42+
customAssert(
43+
isTracerInstalled(false),
44+
true,
45+
"tracer install is not delayed when log manager system property is present.");
4446
customAssert(
4547
isJmxfetchStarted(false),
4648
false,
@@ -57,8 +59,6 @@ public static void main(final String... args) throws Exception {
5759
.getClassLoader()
5860
.loadClass(System.getProperty("java.util.logging.manager")),
5961
"Javaagent should not prevent setting a custom log manager");
60-
customAssert(
61-
isTracerInstalled(true), true, "tracer should be installed after loading LogManager.");
6262
customAssert(
6363
isJmxfetchStarted(true), true, "jmxfetch should start after loading LogManager.");
6464
if (isJFRSupported()) {
@@ -67,8 +67,10 @@ public static void main(final String... args) throws Exception {
6767
}
6868
} else if (System.getenv("JBOSS_HOME") != null) {
6969
System.out.println("JBOSS_HOME != null");
70-
assertTraceInstallationDelayed(
71-
"tracer install must be delayed when JBOSS_HOME property is present.");
70+
customAssert(
71+
isTracerInstalled(false),
72+
true,
73+
"tracer install is not delayed when JBOSS_HOME property is present.");
7274
customAssert(
7375
isJmxfetchStarted(false),
7476
false,
@@ -85,10 +87,6 @@ public static void main(final String... args) throws Exception {
8587
.getClassLoader()
8688
.loadClass(System.getProperty("java.util.logging.manager")),
8789
"Javaagent should not prevent setting a custom log manager");
88-
customAssert(
89-
isTracerInstalled(true),
90-
true,
91-
"tracer should be installed after loading with JBOSS_HOME set.");
9290
customAssert(
9391
isJmxfetchStarted(true),
9492
true,
@@ -128,17 +126,6 @@ private static void customAssert(
128126
}
129127
}
130128

131-
private static void assertTraceInstallationDelayed(final String message) {
132-
if (okHttpMayIndirectlyLoadJUL()) {
133-
customAssert(isTracerInstalled(false), false, message);
134-
} else {
135-
customAssert(
136-
isTracerInstalled(false),
137-
true,
138-
"We can safely install tracer on java9+ since it doesn't indirectly trigger logger manager init");
139-
}
140-
}
141-
142129
private static void assertProfilingStartupDelayed(final String message) {
143130
if (okHttpMayIndirectlyLoadJUL()) {
144131
customAssert(isProfilingStarted(false), false, message);

dd-smoke-tests/log-injection/src/test/groovy/datadog/smoketest/LogInjectionSmokeTest.groovy

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,10 @@ abstract class LogInjectionSmokeTest extends AbstractSmokeTest {
313313
}
314314

315315
if (supportsDirectLogSubmission()) {
316+
int expectedLogLineCount = 7
317+
if ("IBM Corporation" == System.getProperty("java.vm.vendor")) {
318+
expectedLogLineCount = 3
319+
}
316320
assertParsedJsonLinesWithInjection(mockBackend.waitForLogs(7), firstTraceId, firstSpanId, secondTraceId, secondSpanId, forthTraceId, forthSpanId)
317321
}
318322
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ private CoreTracer(
689689
}
690690
pendingTraceBuffer.start();
691691

692-
this.writer.start();
692+
sharedCommunicationObjects.whenReady(this.writer::start);
693693

694694
metricsAggregator = createMetricsAggregator(config, sharedCommunicationObjects);
695695
// Schedule the metrics aggregator to begin reporting after a random delay of 1 to 10 seconds
@@ -705,7 +705,8 @@ private CoreTracer(
705705
} else {
706706
this.dataStreamsMonitoring = dataStreamsMonitoring;
707707
}
708-
this.dataStreamsMonitoring.start();
708+
709+
sharedCommunicationObjects.whenReady(this.dataStreamsMonitoring::start);
709710

710711
// Create default extractor from config if not provided and decorate it with DSM extractor
711712
HttpCodec.Extractor builtExtractor =

0 commit comments

Comments
 (0)