Skip to content

Commit

Permalink
Merge pull request #6196 from DataDog/jpbempel/condition-smoke-test
Browse files Browse the repository at this point in the history
Add smoke tests for probes with conditions
  • Loading branch information
jpbempel authored Nov 10, 2023
2 parents a36099f + 57ee49f commit f15f4b4
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package datadog.smoketest;

import static com.datadog.debugger.el.DSL.and;
import static com.datadog.debugger.el.DSL.eq;
import static com.datadog.debugger.el.DSL.gt;
import static com.datadog.debugger.el.DSL.len;
import static com.datadog.debugger.el.DSL.nullValue;
import static com.datadog.debugger.el.DSL.ref;
import static com.datadog.debugger.el.DSL.value;
import static com.datadog.debugger.el.DSL.when;
import static com.datadog.debugger.util.LogProbeTestHelper.parseTemplate;
import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -63,7 +68,7 @@ void testFullMethod() throws Exception {
JsonAdapter<List<JsonSnapshotSerializer.IntakeRequest>> adapter = createAdapterForSnapshot();
System.out.println(bodyStr);
Snapshot snapshot = adapter.fromJson(bodyStr).get(0).getDebugger().getSnapshot();
assertEquals("123356536", snapshot.getProbe().getId());
assertEquals(PROBE_ID.getId(), snapshot.getProbe().getId());
assertFullMethodCaptureArgs(snapshot.getCaptures().getEntry());
assertEquals(0, snapshot.getCaptures().getEntry().getLocals().size());
assertNull(snapshot.getCaptures().getEntry().getThrowable());
Expand All @@ -90,7 +95,7 @@ void testFullMethodWithCondition() throws Exception {
.where(MAIN_CLASS_NAME, METHOD_NAME)
.when(
new ProbeCondition(
when(eq(ref("argStr"), DSL.value("foobar"))), "argStr == \"foobar\""))
when(eq(ref("argStr"), value("foobar"))), "argStr == \"foobar\""))
.captureSnapshot(true)
.build();
setCurrentConfiguration(createConfig(probe));
Expand All @@ -102,10 +107,66 @@ void testFullMethodWithCondition() throws Exception {
JsonAdapter<List<JsonSnapshotSerializer.IntakeRequest>> adapter = createAdapterForSnapshot();
System.out.println(bodyStr);
Snapshot snapshot = adapter.fromJson(bodyStr).get(0).getDebugger().getSnapshot();
assertEquals("123356536", snapshot.getProbe().getId());
assertEquals(PROBE_ID.getId(), snapshot.getProbe().getId());
assertFullMethodCaptureArgs(snapshot.getCaptures().getEntry());
}

@Test
@DisplayName("testFullMethodWithConditionAtExit")
void testFullMethodWithConditionAtExit() throws Exception {
final String METHOD_NAME = "fullMethod";
final String EXPECTED_UPLOADS = "3";
LogProbe probe =
LogProbe.builder()
.probeId(PROBE_ID)
.where(MAIN_CLASS_NAME, METHOD_NAME)
.when(
new ProbeCondition(
when(and(gt(len(ref("@return")), value(0)), gt(ref("@duration"), value(0)))),
"len(@return) > 0 && @duration > 0"))
.captureSnapshot(true)
.evaluateAt(MethodLocation.EXIT)
.build();
setCurrentConfiguration(createConfig(probe));
targetProcess = createProcessBuilder(logFilePath, METHOD_NAME, EXPECTED_UPLOADS).start();
RecordedRequest request = retrieveSnapshotRequest();
assertNotNull(request);
assertFalse(logHasErrors(logFilePath, it -> false));
String bodyStr = request.getBody().readUtf8();
JsonAdapter<List<JsonSnapshotSerializer.IntakeRequest>> adapter = createAdapterForSnapshot();
System.out.println(bodyStr);
Snapshot snapshot = adapter.fromJson(bodyStr).get(0).getDebugger().getSnapshot();
assertEquals(PROBE_ID.getId(), snapshot.getProbe().getId());
assertFullMethodCaptureArgs(snapshot.getCaptures().getReturn());
}

@Test
@DisplayName("testFullMethodWithConditionFailed")
void testFullMethodWithConditionFailed() throws Exception {
final String METHOD_NAME = "fullMethod";
final String EXPECTED_UPLOADS = "3";
LogProbe probe =
LogProbe.builder()
.probeId(PROBE_ID)
.where(MAIN_CLASS_NAME, METHOD_NAME)
.when(new ProbeCondition(when(eq(ref("noarg"), nullValue())), "noarg == null"))
.captureSnapshot(true)
.evaluateAt(MethodLocation.EXIT)
.build();
setCurrentConfiguration(createConfig(probe));
targetProcess = createProcessBuilder(logFilePath, METHOD_NAME, EXPECTED_UPLOADS).start();
RecordedRequest request = retrieveSnapshotRequest();
assertNotNull(request);
assertFalse(logHasErrors(logFilePath, it -> false));
String bodyStr = request.getBody().readUtf8();
JsonAdapter<List<JsonSnapshotSerializer.IntakeRequest>> adapter = createAdapterForSnapshot();
System.out.println(bodyStr);
Snapshot snapshot = adapter.fromJson(bodyStr).get(0).getDebugger().getSnapshot();
assertEquals(PROBE_ID.getId(), snapshot.getProbe().getId());
assertEquals(1, snapshot.getEvaluationErrors().size());
assertEquals("Cannot find symbol: noarg", snapshot.getEvaluationErrors().get(0).getMessage());
}

@Test
@DisplayName("testFullMethodWithLogTemplate")
void testFullMethodWithLogTemplate() throws Exception {
Expand All @@ -127,7 +188,7 @@ void testFullMethodWithLogTemplate() throws Exception {
JsonAdapter<List<JsonSnapshotSerializer.IntakeRequest>> adapter = createAdapterForSnapshot();
System.out.println(bodyStr);
JsonSnapshotSerializer.IntakeRequest intakeRequest = adapter.fromJson(bodyStr).get(0);
assertEquals("123356536", intakeRequest.getDebugger().getSnapshot().getProbe().getId());
assertEquals(PROBE_ID.getId(), intakeRequest.getDebugger().getSnapshot().getProbe().getId());
assertEquals(
"log line 42 foobar 3.42 {[key1=val1], [key2=val2], [key3=val3]} [var1, var2, var3]",
intakeRequest.getMessage());
Expand Down Expand Up @@ -184,16 +245,14 @@ void testSamplingSnapshotDefault() throws Exception {
@DisplayName("testSamplingSnapshotDefaultWithConditionAtEntry")
void testSamplingSnapshotDefaultWithConditionAtEntry() throws Exception {
doSamplingSnapshot(
new ProbeCondition(DSL.when(DSL.eq(DSL.value(1), DSL.value(1))), "1 == 1"),
MethodLocation.ENTRY);
new ProbeCondition(DSL.when(DSL.eq(value(1), value(1))), "1 == 1"), MethodLocation.ENTRY);
}

@Test
@DisplayName("testSamplingSnapshotDefaultWithConditionAtExit")
void testSamplingSnapshotDefaultWithConditionAtExit() throws Exception {
doSamplingSnapshot(
new ProbeCondition(DSL.when(DSL.eq(DSL.value(1), DSL.value(1))), "1 == 1"),
MethodLocation.EXIT);
new ProbeCondition(DSL.when(DSL.eq(value(1), value(1))), "1 == 1"), MethodLocation.EXIT);
}

private void doSamplingSnapshot(ProbeCondition probeCondition, MethodLocation evaluateAt)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package datadog.smoketest;

import static org.junit.Assert.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertEquals;

import com.datadog.debugger.agent.ProbeStatus;
import com.datadog.debugger.el.DSL;
import com.datadog.debugger.el.ValueScript;
import com.datadog.debugger.probe.MetricProbe;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -37,6 +40,26 @@ void testMethodMetricCount() throws Exception {
"dynamic.instrumentation.metric.probe.%s:42|c|#debugger.probeid:%s");
}

@Test
@DisplayName("testMethodMetricCountInvalidSymbol")
void testMethodMetricCountInvalidSymbol() throws Exception {
doMethodInvalidMetric(
"fullMethod_count",
MetricProbe.MetricKind.COUNT,
new ValueScript(DSL.ref("noarg"), "noarg"),
"Cannot resolve symbol noarg");
}

@Test
@DisplayName("testMethodMetricCountInvalidType")
void testMethodMetricCountInvalidType() throws Exception {
doMethodInvalidMetric(
"fullMethod_count",
MetricProbe.MetricKind.COUNT,
new ValueScript(DSL.ref("argStr"), "argStr"),
"Incompatible type for expression: java.lang.String with expected types: [long]");
}

@Test
@DisplayName("testMethodMetricGauge")
void testMethodMetricGauge() throws Exception {
Expand Down Expand Up @@ -87,6 +110,39 @@ private void doMethodMetric(
assertNotNull(retrieveStatsdMessage(msgExpected));
}

private void doMethodInvalidMetric(
String metricName, MetricProbe.MetricKind kind, ValueScript script, String expectedMsg)
throws Exception {
final String METHOD_NAME = "fullMethod";
final String EXPECTED_UPLOADS =
"-1"; // wait for TIMEOUT_S for letting the Probe Status to be sent (async)
MetricProbe metricProbe =
MetricProbe.builder()
.probeId(PROBE_ID)
.where(MAIN_CLASS_NAME, METHOD_NAME)
.kind(kind)
.metricName(metricName)
.valueScript(script)
.build();
setCurrentConfiguration(createMetricConfig(metricProbe));
targetProcess = createProcessBuilder(logFilePath, METHOD_NAME, EXPECTED_UPLOADS).start();
AtomicBoolean received = new AtomicBoolean();
AtomicBoolean error = new AtomicBoolean();
registerProbeStatusListener(
probeStatus -> {
if (probeStatus.getDiagnostics().getStatus() == ProbeStatus.Status.RECEIVED) {
received.set(true);
}
if (probeStatus.getDiagnostics().getStatus() == ProbeStatus.Status.ERROR) {
assertEquals(expectedMsg, probeStatus.getDiagnostics().getException().getMessage());
error.set(true);
}
return received.get() && error.get();
});
processRequests();
clearProbeStatusListener();
}

@Test
@DisplayName("testLineMetricInc")
void testLineMetricInc() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,18 @@ public JsonConditionVisitor(JsonWriter jsonWriter) {

@Override
public Void visit(BinaryExpression binaryExpression) {
throw new UnsupportedOperationException("binary expression");
try {
jsonWriter.beginObject();
binaryExpression.getOperator().accept(this);
jsonWriter.beginArray();
binaryExpression.getLeft().accept(this);
binaryExpression.getRight().accept(this);
jsonWriter.endArray();
jsonWriter.endObject();
} catch (IOException ex) {
LOGGER.debug("Cannot serialize: ", ex);
}
return null;
}

@Override
Expand All @@ -100,12 +111,14 @@ public Void visit(BinaryOperator operator) {

@Override
public Void visit(ComparisonExpression comparisonExpression) {
comparisonExpression.getOperator().accept(this);
try {
jsonWriter.beginObject();
comparisonExpression.getOperator().accept(this);
jsonWriter.beginArray();
comparisonExpression.getLeft().accept(this);
comparisonExpression.getRight().accept(this);
jsonWriter.endArray();
jsonWriter.endObject();
} catch (IOException ex) {
LOGGER.debug("Cannot serialize: ", ex);
}
Expand Down Expand Up @@ -169,7 +182,15 @@ public Void visit(IsUndefinedExpression isUndefinedExpression) {

@Override
public Void visit(LenExpression lenExpression) {
throw new UnsupportedOperationException("len expression");
try {
jsonWriter.beginObject();
jsonWriter.name("len");
lenExpression.getSource().accept(this);
jsonWriter.endObject();
} catch (IOException ex) {
LOGGER.debug("Cannot serialize: ", ex);
}
return null;
}

@Override
Expand All @@ -180,8 +201,8 @@ public Void visit(MatchesExpression matchesExpression) {
@Override
public Void visit(NotExpression notExpression) {
try {
jsonWriter.name("not");
jsonWriter.beginObject();
jsonWriter.name("not");
notExpression.getPredicate().accept(this);
jsonWriter.endObject();
} catch (IOException ex) {
Expand Down Expand Up @@ -247,13 +268,7 @@ public Void visit(IndexExpression indexExpression) {

@Override
public Void visit(WhenExpression whenExpression) {
try {
jsonWriter.beginObject();
whenExpression.getExpression().accept(this);
jsonWriter.endObject();
} catch (IOException ex) {
LOGGER.debug("Cannot serialize: ", ex);
}
whenExpression.getExpression().accept(this);
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,6 @@ public void testProbeStatusError() throws Exception {
}
return received.get() && error.get();
});
processRequests();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,6 @@ void testSingleLineSpan() throws Exception {
}
return received.get() && error.get();
});
processRequests();
}
}

0 comments on commit f15f4b4

Please sign in to comment.