Skip to content

Commit 8b63e5a

Browse files
authored
Capture values at entry for method probe (#8169)
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. We are delegating the decision to capture through a new field in CapturedContextInstrumentor
1 parent 07e5d63 commit 8b63e5a

File tree

8 files changed

+64
-14
lines changed

8 files changed

+64
-14
lines changed

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

Lines changed: 6 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;
@@ -693,6 +694,7 @@ private ProbeDefinition selectReferenceDefinition(
693694
MethodLocation evaluateAt = MethodLocation.EXIT;
694695
LogProbe.Capture capture = null;
695696
boolean captureSnapshot = false;
697+
ProbeCondition probeCondition = null;
696698
Where where = capturedContextProbes.get(0).getWhere();
697699
ProbeId probeId = capturedContextProbes.get(0).getProbeId();
698700
for (ProbeDefinition definition : capturedContextProbes) {
@@ -704,6 +706,9 @@ private ProbeDefinition selectReferenceDefinition(
704706
LogProbe logProbe = (LogProbe) definition;
705707
captureSnapshot = captureSnapshot | logProbe.isCaptureSnapshot();
706708
capture = mergeCapture(capture, logProbe.getCapture());
709+
if (probeCondition == null) {
710+
probeCondition = logProbe.getProbeCondition();
711+
}
707712
}
708713
if (definition.getEvaluateAt() == MethodLocation.ENTRY
709714
|| definition.getEvaluateAt() == MethodLocation.DEFAULT) {
@@ -713,6 +718,7 @@ private ProbeDefinition selectReferenceDefinition(
713718
if (hasLogProbe) {
714719
return LogProbe.builder()
715720
.probeId(probeId)
721+
.when(probeCondition)
716722
.where(where)
717723
.evaluateAt(evaluateAt)
718724
.capture(capture)

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/exception/ExceptionProbeManager.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,7 @@ private static ExceptionProbe createMethodProbe(
118118
ExceptionProbeManager exceptionProbeManager, Where where, int chainedExceptionIdx) {
119119
String probeId = UUID.randomUUID().toString();
120120
return new ExceptionProbe(
121-
new ProbeId(probeId, 0),
122-
where,
123-
null,
124-
null,
125-
null,
126-
exceptionProbeManager,
127-
chainedExceptionIdx);
121+
new ProbeId(probeId, 0), where, null, null, exceptionProbeManager, chainedExceptionIdx);
128122
}
129123

130124
public boolean isAlreadyInstrumented(String fingerprint) {

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
public class CapturedContextInstrumentor extends Instrumentor {
7070
private static final Logger LOGGER = LoggerFactory.getLogger(CapturedContextInstrumentor.class);
7171
private final boolean captureSnapshot;
72+
private final boolean captureEntry;
7273
private final Limits limits;
7374
private final LabelNode contextInitLabel = new LabelNode();
7475
private int entryContextVar = -1;
@@ -83,9 +84,11 @@ public CapturedContextInstrumentor(
8384
List<DiagnosticMessage> diagnostics,
8485
List<ProbeId> probeIds,
8586
boolean captureSnapshot,
87+
boolean captureEntry,
8688
Limits limits) {
8789
super(definition, methodInfo, diagnostics, probeIds);
8890
this.captureSnapshot = captureSnapshot;
91+
this.captureEntry = captureEntry;
8992
this.limits = limits;
9093
}
9194

@@ -422,8 +425,7 @@ private void instrumentMethodEnter() {
422425
LabelNode targetNode = new LabelNode();
423426
LabelNode gotoNode = new LabelNode();
424427
insnList.add(new JumpInsnNode(Opcodes.IFEQ, targetNode));
425-
// if evaluation is at exit, skip collecting data at enter
426-
if (definition.getEvaluateAt() != MethodLocation.EXIT) {
428+
if (captureEntry) {
427429
LabelNode inProbeStartLabel = new LabelNode();
428430
insnList.add(inProbeStartLabel);
429431
// stack []

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static com.datadog.debugger.util.ExceptionHelper.getInnerMostThrowable;
44
import static java.util.Collections.emptyList;
55

6+
import com.datadog.debugger.el.DSL;
67
import com.datadog.debugger.el.ProbeCondition;
78
import com.datadog.debugger.exception.ExceptionProbeManager;
89
import com.datadog.debugger.exception.Fingerprinter;
@@ -26,7 +27,6 @@ public class ExceptionProbe extends LogProbe implements ForceMethodInstrumentati
2627
public ExceptionProbe(
2728
ProbeId probeId,
2829
Where where,
29-
ProbeCondition probeCondition,
3030
Capture capture,
3131
Sampling sampling,
3232
ExceptionProbeManager exceptionProbeManager,
@@ -40,7 +40,8 @@ public ExceptionProbe(
4040
null,
4141
null,
4242
true,
43-
probeCondition,
43+
// forcing a useless condition to be instrumented with captureEntry=false
44+
new ProbeCondition(DSL.when(DSL.TRUE), "true"),
4445
capture,
4546
sampling);
4647
this.exceptionProbeManager = exceptionProbeManager;

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,16 @@ public Sampling getSampling() {
409409
@Override
410410
public InstrumentationResult.Status instrument(
411411
MethodInfo methodInfo, List<DiagnosticMessage> diagnostics, List<ProbeId> probeIds) {
412+
// if evaluation is at exit and with condition, skip collecting data at entry
413+
boolean captureEntry = !(getEvaluateAt() == MethodLocation.EXIT && hasCondition());
412414
return new CapturedContextInstrumentor(
413-
this, methodInfo, diagnostics, probeIds, isCaptureSnapshot(), toLimits(getCapture()))
415+
this,
416+
methodInfo,
417+
diagnostics,
418+
probeIds,
419+
isCaptureSnapshot(),
420+
captureEntry,
421+
toLimits(getCapture()))
414422
.instrument();
415423
}
416424

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,9 @@ public SpanDecorationProbe(
135135
@Override
136136
public InstrumentationResult.Status instrument(
137137
MethodInfo methodInfo, List<DiagnosticMessage> diagnostics, List<ProbeId> probeIds) {
138+
boolean captureEntry = evaluateAt != MethodLocation.EXIT;
138139
return new CapturedContextInstrumentor(
139-
this, methodInfo, diagnostics, probeIds, false, Limits.DEFAULT)
140+
this, methodInfo, diagnostics, probeIds, false, captureEntry, Limits.DEFAULT)
140141
.instrument();
141142
}
142143

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ public TriggerProbe(ProbeId probeId, Where where) {
5454
@Override
5555
public InstrumentationResult.Status instrument(
5656
MethodInfo methodInfo, List<DiagnosticMessage> diagnostics, List<ProbeId> probeIds) {
57-
return new CapturedContextInstrumentor(this, methodInfo, diagnostics, probeIds, false, null)
57+
return new CapturedContextInstrumentor(
58+
this, methodInfo, diagnostics, probeIds, false, false, null)
5859
.instrument();
5960
}
6061

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)