8000 Capture values at entry for method probe · DataDog/dd-trace-java@839399b · GitHub
[go: up one dir, main page]

Skip to content

Commit 839399b

Browse files
committed
Capture values at entry for method probe
method probe when evaluateAt is Exit and no condition should capture entry values. When there is a condition, entry values are not captured instrumentation check the presence of the condition to generate the entry instrumentation or not. therefore, the dummy definition used when duplicate probes need to merge the probe conditions if at least one probe has one condition.
1 parent 54d4a6f commit 839399b

File tree

4 files changed

+54
-5
lines changed

4 files changed

+54
-5
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static java.util.Collections.singletonList;
44
import static java.util.stream.Collectors.toList;
55

6+
import com.datadog.debugger.el.ProbeCondition;
67
import com.datadog.debugger.instrumentation.DiagnosticMessage;
78
import com.datadog.debugger.instrumentation.InstrumentationResult;
89
import com.datadog.debugger.instrumentation.MethodInfo;
@@ -691,6 +692,7 @@ private ProbeDefinition selectReferenceDefinition(
691692
MethodLocation evaluateAt = MethodLocation.EXIT;
692693
LogProbe.Capture capture = null;
693694
boolean captureSnapshot = false;
695+
ProbeCondition probeCondition = null;
694696
Where where = capturedContextProbes.get(0).getWhere();
695697
ProbeId probeId = capturedContextProbes.get(0).getProbeId();
696698
for (ProbeDefinition definition : capturedContextProbes) {
@@ -702,6 +704,10 @@ private ProbeDefinition selectReferenceDefinition(
702704
LogProbe logProbe = (LogProbe) definition;
703705
captureSnapshot = captureSnapshot | logProbe.isCaptureSnapshot();
704706
capture = mergeCapture(capture, logProbe.getCapture());
707+
probeCondition =
708+
probeCondition == null && logProbe.getProbeCondition() != null
709+
? logProbe.getProbeCondition()
710+
: probeCondition;
705711
}
706712
if (definition.getEvaluateAt() == MethodLocation.ENTRY
707713
|| definition.getEvaluateAt() == MethodLocation.DEFAULT) {
@@ -711,6 +717,7 @@ private ProbeDefinition selectReferenceDefinition(
711717
if (hasLogProbe) {
712718
return LogProbe.builder()
713719
.probeId(probeId)
720+
.when(probeCondition)
714721
.where(where)
715722
.evaluateAt(evaluateAt)
716723
.capture(capture)

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/instrumentation/CapturedContextInstrumentor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,8 @@ private void instrumentMethodEnter() {
424424
LabelNode targetNode = new LabelNode();
425425
LabelNode gotoNode = new LabelNode();
426426
insnList.add(new JumpInsnNode(Opcodes.IFEQ, targetNode));
427-
// if evaluation is at exit, skip collecting data at enter
428-
if (definition.getEvaluateAt() != MethodLocation.EXIT) {
427+
// if evaluation is at exit and with condition, skip collecting data at enter
428+
if (definition.getEvaluateAt() != MethodLocation.EXIT || !definition.hasCondition()) {
429429
LabelNode inProbeStartLabel = new LabelNode();
430430
insnList.add(inProbeStartLabel);
431431
// stack []

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/probe/ExceptionProbe.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,18 @@ public CapturedContext.Status createStatus() {
6161
@Override
6262
public void evaluate(
6363
CapturedContext context, CapturedContext.Status status, MethodLocation methodLocation) {
64-
if (!(status instanceof ExceptionProbeStatus)) {
64+
ExceptionProbeStatus exceptionStatus;
65+
if (status instanceof ExceptionProbeStatus) {
66+
exceptionStatus = (ExceptionProbeStatus) status;
67+
} else {
6568
throw new IllegalStateException("Invalid status: " + status.getClass());
6669
}
6770
if (methodLocation != MethodLocation.EXIT) {
6871
return;
6972
}
73+
// reset capture flag as we are at exit, consider at entry always capture
74+
// only the evaluation at exit decide to send the snapshot or not based on exception evaluation
75+
exceptionStatus.setCapture(false);
7076
if (context.getCapturedThrowable() == null) {
7177
return;
7278
}
@@ -81,7 +87,6 @@ public void evaluate(
8187
if (exceptionProbeManager.shouldCaptureException(fingerprint)) {
8288
LOGGER.debug("Capturing exception matching fingerprint: {}", fingerprint);
8389
// capture only on uncaught exception matching the fingerprint
84-
ExceptionProbeStatus exceptionStatus = (ExceptionProbeStatus) status;
8590
ExceptionProbeManager.ThrowableState state =
8691
exceptionProbeManager.getStateByThrowable(innerMostThrowable);
8792
if (state != null) {
@@ -147,7 +152,7 @@ public void buildLocation(InstrumentationResult result) {
147152
}
148153

149154
public static class ExceptionProbeStatus extends LogStatus {
150-
private boolean capture;
155+
private boolean capture = true;
151156

152157
public ExceptionProbeStatus(ProbeImplementation probeImplementation) {
153158
super(probeImplementation);

dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/agent/CapturedSnapshotTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,43 @@ public void methodProbe() throws IOException, URISyntaxException {
134134
assertEquals("CapturedSnapshot01.main", snapshot.getStack().get(0).getFunction());
135135
}
136136

137+
@Test
138+
public void methodProbeAtExit() throws IOException, URISyntaxException {
139+
final String CLASS_NAME = "CapturedSnapshot01";
140+
TestSnapshotListener listener =
141+
installSingleProbeAtExit(CLASS_NAME, "main", "int (java.lang.String)");
142+
Class<?> testClass = compileAndLoadClass(CLASS_NAME);
143+
int result = Reflect.onClass(testClass).call("main", "1").get();
144+
assertEquals(3, result);
145+
Snapshot snapshot = assertOneSnapshot(listener);
146+
assertCaptureArgs(snapshot.getCaptures().getEntry(), "arg", "java.lang.String", "1");
147+
assertCaptureArgs(snapshot.getCaptures().getReturn(), "arg", "java.lang.String", "1");
148+
assertTrue(snapshot.getDuration() > 0);
149+
assertTrue(snapshot.getStack().size() > 0);
150+
assertEquals("CapturedSnapshot01.main", snapshot.getStack().get(0).getFunction());
151+
}
152+
153+
@Test
154+
public void methodProbeAtExitWithCondition() throws IOException, URISyntaxException {
155+
final String CLASS_NAME = "CapturedSnapshot01";
156+
LogProbe probe =
157+
createProbeBuilder(PROBE_ID, CLASS_NAME, "main", "int (java.lang.String)")
158+
.when(
159+
new ProbeCondition(DSL.when(DSL.eq(DSL.ref("arg"), DSL.value("1"))), "arg == '1'"))
160+
.evaluateAt(MethodLocation.EXIT)
161+
.build();
162+
TestSnapshotListener listener = installProbes(probe);
163+
Class<?> testClass = compileAndLoadClass(CLASS_NAME);
164+
int result = Reflect.onClass(testClass).call("main", "1").get();
165+
assertEquals(3, result);
166+
Snapshot snapshot = assertOneSnapshot(listener);
167+
assertEquals(CapturedContext.EMPTY_CAPTURING_CONTEXT, snapshot.getCaptures().getEntry());
168+
assertCaptureArgs(snapshot.getCaptures().getReturn(), "arg", "java.lang.String", "1");
169+
assertTrue(snapshot.getDuration() > 0);
170+
assertTrue(snapshot.getStack().size() > 0);
171+
assertEquals("CapturedSnapshot01.main", snapshot.getStack().get(0).getFunction());
172+
}
173+
137174
@Test
138175
public void localVarHoistingNoPreviousStore() throws IOException, URISyntaxException {
139176
final String CLASS_NAME = "com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper";

0 commit comments

Comments
 (0)
0