Skip to content

Commit 6e5afe4

Browse files
committed
Fix debugger start when endpoints aren't available
catch exception throws during common init and keep the product stopped SymDB, Exception Replay and Code Origin requires CommonInit which may in some cases throw exception (endpoints are not available from Datadog Agent)
1 parent a08b93a commit 6e5afe4

File tree

3 files changed

+81
-37
lines changed

3 files changed

+81
-37
lines changed

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/agent/DebuggerAgent.java

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -110,38 +110,44 @@ public static synchronized void run(
110110
TracerFlare.addReporter(DebuggerAgent::addReportToFlare);
111111
}
112112

113-
private static void commonInit(Config config) {
113+
private static boolean commonInit(Config config) {
114114
if (!commonInitDone.compareAndSet(false, true)) {
115-
return;
115+
return true;
116+
}
117+
try {
118+
configurationPoller = sharedCommunicationObjects.configurationPoller(config);
119+
Redaction.addUserDefinedKeywords(config);
120+
Redaction.addUserDefinedTypes(config);
121+
DDAgentFeaturesDiscovery ddAgentFeaturesDiscovery =
122+
sharedCommunicationObjects.featuresDiscovery(config);
123+
ddAgentFeaturesDiscovery.discoverIfOutdated();
124+
agentVersion = ddAgentFeaturesDiscovery.getVersion();
125+
String diagnosticEndpoint = getDiagnosticEndpoint(config, ddAgentFeaturesDiscovery);
126+
ProbeStatusSink probeStatusSink =
127+
new ProbeStatusSink(
128+
config, diagnosticEndpoint, ddAgentFeaturesDiscovery.supportsDebuggerDiagnostics());
129+
DebuggerSink debuggerSink =
130+
createDebuggerSink(config, ddAgentFeaturesDiscovery, probeStatusSink);
131+
debuggerSink.start();
132+
configurationUpdater =
133+
new ConfigurationUpdater(
134+
instrumentation,
135+
DebuggerAgent::createTransformer,
136+
config,
137+
debuggerSink,
138+
classesToRetransformFinder);
139+
sink = debuggerSink;
140+
DebuggerContext.initProbeResolver(configurationUpdater);
141+
DebuggerContext.initMetricForwarder(new StatsdMetricForwarder(config, probeStatusSink));
142+
DebuggerContext.initClassFilter(new DenyListHelper(null)); // default hard coded deny list
143+
snapshotSerializer = new JsonSnapshotSerializer();
144+
DebuggerContext.initValueSerializer(snapshotSerializer);
145+
DebuggerContext.initTracer(new DebuggerTracer(debuggerSink.getProbeStatusSink()));
146+
return true;
147+
} catch (Exception ex) {
148+
LOGGER.debug("Failed to init common component for debugger agent", ex);
149+
return false;
116150
}
117-
configurationPoller = sharedCommunicationObjects.configurationPoller(config);
118-
Redaction.addUserDefinedKeywords(config);
119-
Redaction.addUserDefinedTypes(config);
120-
DDAgentFeaturesDiscovery ddAgentFeaturesDiscovery =
121-
sharedCommunicationObjects.featuresDiscovery(config);
122-
ddAgentFeaturesDiscovery.discoverIfOutdated();
123-
agentVersion = ddAgentFeaturesDiscovery.getVersion();
124-
String diagnosticEndpoint = getDiagnosticEndpoint(config, ddAgentFeaturesDiscovery);
125-
ProbeStatusSink probeStatusSink =
126-
new ProbeStatusSink(
127-
config, diagnosticEndpoint, ddAgentFeaturesDiscovery.supportsDebuggerDiagnostics());
128-
DebuggerSink debuggerSink =
129-
createDebuggerSink(config, ddAgentFeaturesDiscovery, probeStatusSink);
130-
debuggerSink.start();
131-
configurationUpdater =
132-
new ConfigurationUpdater(
133-
instrumentation,
134-
DebuggerAgent::createTransformer,
135-
config,
136-
debuggerSink,
137-
classesToRetransformFinder);
138-
sink = debuggerSink;
139-
DebuggerContext.initProbeResolver(configurationUpdater);
140-
DebuggerContext.initMetricForwarder(new StatsdMetricForwarder(config, probeStatusSink));
141-
DebuggerContext.initClassFilter(new DenyListHelper(null)); // default hard coded deny list
142-
snapshotSerializer = new JsonSnapshotSerializer();
143-
DebuggerContext.initValueSerializer(snapshotSerializer);
144-
DebuggerContext.initTracer(new DebuggerTracer(debuggerSink.getProbeStatusSink()));
145151
}
146152

147153
private static void initClassNameFilter() {
@@ -155,7 +161,10 @@ public static void startDynamicInstrumentation(Config config) {
155161
return;
156162
}
157163
LOGGER.info("Starting Dynamic Instrumentation");
158-
commonInit(config);
164+
if (!commonInit(config)) {
165+
dynamicInstrumentationEnabled.set(false);
166+
return;
167+
}
159168
String probeFileLocation = config.getDynamicInstrumentationProbeFile();
160169
if (probeFileLocation != null) {
161170
Path probeFilePath = Paths.get(probeFileLocation);
@@ -205,7 +214,10 @@ public static void startSymbolDatabase(Config config) {
205214
return;
206215
}
207216
LOGGER.debug("Starting Symbol Database");
208-
commonInit(config);
217+
if (!commonInit(config)) {
218+
symDBEnabled.set(false);
219+
return;
220+
}
209221
initClassNameFilter();
210222
List<ScopeFilter> scopeFilters =
211223
Arrays.asList(new AvroFilter(), new ProtoFilter(), new WireFilter());
@@ -254,7 +266,10 @@ public static void startExceptionReplay(Config config) {
254266
return;
255267
}
256268
LOGGER.info("Starting Exception Replay");
257-
commonInit(config);
269+
if (!commonInit(config)) {
270+
exceptionReplayEnabled.set(false);
271+
return;
272+
}
258273
initClassNameFilter();
259274
if (config.isCiVisibilityEnabled()) {
260275
exceptionDebugger =
@@ -285,7 +300,10 @@ public static void startCodeOriginForSpans(Config config) {
285300
return;
286301
}
287302
LOGGER.debug("Starting Code Origin for spans");
288-
commonInit(config);
303+
if (!commonInit(config)) {
304+
codeOriginEnabled.set(false);
305+
return;
306+
}
289307
initClassNameFilter();
290308
DebuggerContext.initClassNameFilter(classNameFilter);
291309
DebuggerContext.initCodeOrigin(new DefaultCodeOriginRecorder(config, configurationUpdater));

dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/BaseIntegrationTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public abstract class BaseIntegrationTest {
9595
public static final String APM_TRACING_PRODUCT = "APM_TRACING";
9696

9797
protected MockWebServer datadogAgentServer;
98-
private MockDispatcher probeMockDispatcher;
98+
protected MockDispatcher probeMockDispatcher;
9999
private StatsDServer statsDServer;
100100
private HttpUrl probeUrl;
101101
private HttpUrl snapshotUrl;
@@ -410,7 +410,7 @@ protected String retrieveStatsdMessage(String str) {
410410
return statsDServer.waitForMessage(str);
411411
}
412412

413-
private MockResponse datadogAgentDispatch(RecordedRequest request) {
413+
protected MockResponse datadogAgentDispatch(RecordedRequest request) {
414414
LOG.info("datadogAgentDispatch request path: {}", request.getPath());
415415
if (request.getPath().equals("/info")) {
416416
return AGENT_INFO_RESPONSE;
@@ -591,7 +591,7 @@ protected static boolean logHasErrors(Path logFilePath, Function<String, Boolean
591591
}
592592
}
593593

594-
private static class MockDispatcher extends okhttp3.mockwebserver.QueueDispatcher {
594+
protected static class MockDispatcher extends okhttp3.mockwebserver.QueueDispatcher {
595595
private Function<RecordedRequest, MockResponse> dispatcher;
596596

597597
@Override

dd-smoke-tests/debugger-integration-tests/src/test/java/datadog/smoketest/InProductEnablementIntegrationTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import java.nio.file.Path;
77
import java.util.ArrayList;
88
import java.util.List;
9+
import okhttp3.mockwebserver.MockResponse;
10+
import okhttp3.mockwebserver.RecordedRequest;
911
import org.junit.jupiter.api.DisplayName;
1012
import org.junit.jupiter.api.Test;
1113

@@ -90,6 +92,30 @@ void testExceptionReplayEnablement() throws Exception {
9092
waitForReTransformation(appUrl); // wait for retransformation of removed probes
9193
}
9294

95+
// TODO test for failure of starting ER, SymDB and DI: should degrade gracefully
96+
// TODO by not providing endpoints
97+
98+
@Test
99+
@DisplayName("testExceptionReplayEnablementFailure")
100+
void testExceptionReplayEnablementFailure() throws Exception {
101+
additionalJvmArgs.add("-Ddd.symbol.database.upload.enabled=false"); // enabled by default
102+
additionalJvmArgs.add("-Ddd.exception.replay.enabled=true");
103+
additionalJvmArgs.add("-Ddd.third.party.excludes=datadog.smoketest");
104+
this.probeMockDispatcher.setDispatcher(this::noEndpointDispatch);
105+
appUrl = startAppAndAndGetUrl();
106+
waitForSpecificLine(appUrl, "Failed to init common component for debugger agent");
107+
}
108+
109+
private MockResponse noEndpointDispatch(RecordedRequest request) {
110+
if (request.getPath().equals("/info")) {
111+
// no debugger endpoints
112+
String info =
113+
"{\"endpoints\": [\"" + TRACE_URL_PATH + "\", \"" + LOG_UPLOAD_URL_PATH + "\"]}";
114+
return new MockResponse().setResponseCode(200).setBody(info);
115+
}
116+
return datadogAgentDispatch(request);
117+
}
118+
93119
private void waitForFeatureStarted(String appUrl, String feature) throws IOException {
94120
String line = "INFO com.datadog.debugger.agent.DebuggerAgent - Started " + feature;
95121
waitForSpecificLine(appUrl, line);

0 commit comments

Comments
 (0)