Skip to content

Commit dc125de

Browse files
authored
Merge pull request DataDog#5816 from DataDog/jpbempel/smoke-tests
Add metric smoke tests
2 parents 89c6d63 + e7584da commit dc125de

File tree

5 files changed

+372
-131
lines changed

5 files changed

+372
-131
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package datadog.smoketest;
2+
3+
import static org.junit.Assert.assertFalse;
4+
import static org.junit.Assert.assertNotNull;
5+
import static org.junit.Assert.assertTrue;
6+
7+
import com.datadog.debugger.agent.JsonSnapshotSerializer;
8+
import com.datadog.debugger.probe.LogProbe;
9+
import com.datadog.debugger.sink.Snapshot;
10+
import com.squareup.moshi.JsonAdapter;
11+
import java.util.List;
12+
import java.util.concurrent.TimeUnit;
13+
import okhttp3.mockwebserver.MockResponse;
14+
import okhttp3.mockwebserver.RecordedRequest;
15+
import org.junit.jupiter.api.DisplayName;
16+
import org.junit.jupiter.api.Test;
17+
18+
public class AgentDebuggerIntegrationTest extends SimpleAppDebuggerIntegrationTest {
19+
@Test
20+
@DisplayName("testLatestJdk")
21+
void testLatestJdk() throws Exception {
22+
final String EXPECTED_UPLOADS = "3";
23+
LogProbe probe = LogProbe.builder().where("App", "getGreeting").build();
24+
setCurrentConfiguration(createConfig(probe));
25+
String classpath = System.getProperty("datadog.smoketest.shadowJar.external.path");
26+
if (classpath == null) {
27+
return; // execute test only if classpath is provided for the latest jdk
28+
}
29+
List<String> commandParams = getDebuggerCommandParams();
30+
targetProcess =
31+
ProcessBuilderHelper.createProcessBuilder(
32+
classpath, commandParams, logFilePath, "App", EXPECTED_UPLOADS)
33+
.start();
34+
RecordedRequest request = retrieveSnapshotRequest();
35+
assertNotNull(request);
36+
assertFalse(logHasErrors(logFilePath, it -> false));
37+
String bodyStr = request.getBody().readUtf8();
38+
LOG.info("got snapshot: {}", bodyStr);
39+
JsonAdapter<List<JsonSnapshotSerializer.IntakeRequest>> adapter = createAdapterForSnapshot();
40+
Snapshot snapshot = adapter.fromJson(bodyStr).get(0).getDebugger().getSnapshot();
41+
assertNotNull(snapshot);
42+
}
43+
44+
@Test
45+
@DisplayName("testShutdown")
46+
void testShutdown() throws Exception {
47+
final String METHOD_NAME = "emptyMethod";
48+
final String EXPECTED_UPLOADS = "3";
49+
LogProbe probe =
50+
LogProbe.builder().probeId(PROBE_ID).where(MAIN_CLASS_NAME, METHOD_NAME).build();
51+
setCurrentConfiguration(createConfig(probe));
52+
targetProcess = createProcessBuilder(logFilePath, METHOD_NAME, EXPECTED_UPLOADS).start();
53+
54+
RecordedRequest request = retrieveSnapshotRequest();
55+
assertFalse(logHasErrors(logFilePath, it -> false));
56+
assertNotNull(request);
57+
assertTrue(request.getBodySize() > 0);
58+
59+
// Wait for the app exit with some extra time.
60+
// The expectation is that agent doesn't prevent app from exiting.
61+
assertTrue(targetProcess.waitFor(REQUEST_WAIT_TIMEOUT + 10, TimeUnit.SECONDS));
62+
}
63+
64+
@Test
65+
@DisplayName("testDestroy")
66+
void testDestroy() throws Exception {
67+
final String METHOD_NAME = "fullMethod";
68+
final String EXPECTED_UPLOADS = "3";
69+
LogProbe probe =
70+
LogProbe.builder().probeId(PROBE_ID).where(MAIN_CLASS_NAME, METHOD_NAME).build();
71+
setCurrentConfiguration(createConfig(probe));
72+
datadogAgentServer.enqueue(
73+
new MockResponse()
74+
.setHeadersDelay(REQUEST_WAIT_TIMEOUT * 2, TimeUnit.SECONDS)
75+
.setResponseCode(200));
76+
// wait for 3 snapshots (2 status + 1 snapshot)
77+
targetProcess = createProcessBuilder(logFilePath, METHOD_NAME, EXPECTED_UPLOADS).start();
78+
79+
RecordedRequest request = retrieveSnapshotRequest();
80+
assertNotNull(request);
81+
assertTrue(request.getBodySize() > 0);
82+
retrieveSnapshotRequest();
83+
targetProcess.destroy();
84+
// Wait for the app exit with some extra time.
85+
// The expectation is that agent doesn't prevent app from exiting.
86+
assertTrue(targetProcess.waitFor(REQUEST_WAIT_TIMEOUT + 10, TimeUnit.SECONDS));
87+
}
88+
}

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

+83-10
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88
import com.datadog.debugger.agent.JsonSnapshotSerializer;
99
import com.datadog.debugger.agent.ProbeStatus;
1010
import com.datadog.debugger.probe.LogProbe;
11+
import com.datadog.debugger.probe.MetricProbe;
1112
import com.datadog.debugger.util.MoshiHelper;
1213
import com.datadog.debugger.util.MoshiSnapshotTestHelper;
1314
import com.squareup.moshi.JsonAdapter;
1415
import com.squareup.moshi.Types;
1516
import datadog.trace.bootstrap.debugger.CapturedContext;
1617
import java.io.IOException;
18+
import java.net.DatagramPacket;
19+
import java.net.DatagramSocket;
20+
import java.net.SocketException;
1721
import java.nio.file.Files;
1822
import java.nio.file.Path;
1923
import java.nio.file.Paths;
@@ -23,6 +27,8 @@
2327
import java.util.Collections;
2428
import java.util.List;
2529
import java.util.UUID;
30+
import java.util.concurrent.ArrayBlockingQueue;
31+
import java.util.concurrent.BlockingQueue;
2632
import java.util.concurrent.TimeUnit;
2733
import java.util.function.Function;
2834
import okhttp3.HttpUrl;
@@ -44,7 +50,9 @@ public abstract class BaseIntegrationTest {
4450
protected static final int REQUEST_WAIT_TIMEOUT = 10;
4551
private static final Path LOG_FILE_BASE =
4652
Paths.get(
47-
buildDirectory(), "reports", "testProcess." + DebuggerIntegrationTest.class.getName());
53+
buildDirectory(),
54+
"reports",
55+
"testProcess." + SimpleAppDebuggerIntegrationTest.class.getName());
4856
private static final String INFO_CONTENT =
4957
"{\"endpoints\": [\"v0.4/traces\", \"debugger/v1/input\", \"v0.7/config\"]}";
5058
private static final MockResponse AGENT_INFO_RESPONSE =
@@ -54,7 +62,7 @@ public abstract class BaseIntegrationTest {
5462

5563
protected MockWebServer datadogAgentServer;
5664
private MockDispatcher probeMockDispatcher;
57-
65+
private StatsDServer statsDServer;
5866
private HttpUrl probeUrl;
5967
private HttpUrl snapshotUrl;
6068
protected Path logFilePath;
@@ -77,6 +85,9 @@ void setup(TestInfo testInfo) throws Exception {
7785
probeUrl = datadogAgentServer.url(PROBE_URL_PATH);
7886
LOG.info("DatadogAgentServer on {}", datadogAgentServer.getPort());
7987
snapshotUrl = datadogAgentServer.url(SNAPSHOT_URL_PATH);
88+
statsDServer = new StatsDServer();
89+
statsDServer.start();
90+
LOG.info("statsDServer on {}", statsDServer.getPort());
8091
logFilePath = LOG_FILE_BASE.resolve(testInfo.getDisplayName() + ".log");
8192
}
8293

@@ -86,6 +97,7 @@ void teardown() throws Exception {
8697
targetProcess.destroyForcibly();
8798
}
8899
datadogAgentServer.shutdown();
100+
statsDServer.close();
89101
}
90102

91103
protected ProcessBuilder createProcessBuilder(Path logFilePath, String... params) {
@@ -109,16 +121,10 @@ protected List<String> getDebuggerCommandParams() {
109121
"-Ddd.jmxfetch.start-delay=0",
110122
"-Ddd.jmxfetch.enabled=false",
111123
"-Ddd.dynamic.instrumentation.enabled=true",
112-
// "-Ddd.remote_config.enabled=true", // default
113124
"-Ddd.remote_config.poll_interval.seconds=1",
114-
/*"-Ddd.remote_config.integrity_check.enabled=false",
115-
"-Ddd.dynamic.instrumentation.probe.url=http://localhost:"
116-
+ probeServer.getPort()
117-
+ PROBE_URL_PATH,
118-
"-Ddd.dynamic.instrumentation.snapshot.url=http://localhost:"
119-
+ snapshotServer.getPort()
120-
+ SNAPSHOT_URL_PATH,*/
121125
"-Ddd.trace.agent.url=http://localhost:" + datadogAgentServer.getPort(),
126+
"-Ddd.jmxfetch.statsd.port=" + statsDServer.getPort(),
127+
"-Ddd.dynamic.instrumentation.classfile.dump.enabled=true",
122128
// to verify each snapshot upload one by one
123129
"-Ddd.dynamic.instrumentation.upload.batch.size=1",
124130
// flush uploads every 100ms to have quick tests
@@ -156,6 +162,10 @@ protected ProbeStatus retrieveProbeStatusRequest() throws Exception {
156162
return probeStatuses.get(0);
157163
}
158164

165+
protected String retrieveStatsdMessage(String str) {
166+
return statsDServer.waitForMessage(str);
167+
}
168+
159169
private MockResponse datadogAgentDispatch(RecordedRequest request) {
160170
LOG.info("datadogAgentDispatch request path: {}", request.getPath());
161171
if (request.getPath().equals("/info")) {
@@ -221,6 +231,13 @@ protected Configuration createConfig(LogProbe logProbe) {
221231
return createConfig(Arrays.asList(logProbe));
222232
}
223233

234+
protected Configuration createMetricConfig(MetricProbe metricProbe) {
235+
return Configuration.builder()
236+
.setService(getAppId())
237+
.addMetricProbes(Collections.singletonList(metricProbe))
238+
.build();
239+
}
240+
224241
protected Configuration createConfig(Collection<LogProbe> logProbes) {
225242
return new Configuration(getAppId(), logProbes);
226243
}
@@ -301,4 +318,60 @@ public void setDispatcher(Function<RecordedRequest, MockResponse> dispatcher) {
301318
this.dispatcher = dispatcher;
302319
}
303320
}
321+
322+
private static class StatsDServer extends Thread {
323+
private final DatagramSocket socket;
324+
private final BlockingQueue<String> msgQueue = new ArrayBlockingQueue<>(32);
325+
private volatile String lastMessage;
326+
private volatile boolean running = true;
327+
328+
StatsDServer() throws SocketException {
329+
socket = new DatagramSocket();
330+
}
331+
332+
@Override
333+
public void run() {
334+
byte[] buf = new byte[1024];
335+
DatagramPacket packet = new DatagramPacket(buf, buf.length);
336+
while (running) {
337+
try {
338+
socket.receive(packet);
339+
} catch (IOException e) {
340+
throw new RuntimeException(e);
341+
}
342+
lastMessage = new String(packet.getData(), 0, packet.getLength());
343+
System.out.println("received statsd: " + lastMessage);
344+
try {
345+
msgQueue.offer(lastMessage, 30, TimeUnit.SECONDS);
346+
} catch (InterruptedException e) {
347+
throw new RuntimeException(e);
348+
}
349+
}
350+
socket.close();
351+
}
352+
353+
String lastMessage() {
354+
return lastMessage;
355+
}
356+
357+
String waitForMessage(String str) {
358+
String msg;
359+
do {
360+
try {
361+
msg = msgQueue.poll(30, TimeUnit.SECONDS);
362+
} catch (InterruptedException e) {
363+
throw new RuntimeException(e);
364+
}
365+
} while (msg != null && !msg.contains(str));
366+
return msg;
367+
}
368+
369+
void close() {
370+
running = false;
371+
}
372+
373+
int getPort() {
374+
return socket.getLocalPort();
375+
}
376+
}
304377
}

0 commit comments

Comments
 (0)