Skip to content

Commit e8e9292

Browse files
authored
Only decorate spans without code origin information (#8105)
1 parent a3e9bda commit e8e9292

File tree

3 files changed

+157
-36
lines changed

3 files changed

+157
-36
lines changed

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

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import static datadog.trace.api.DDTags.DD_CODE_ORIGIN_TYPE;
66
import static java.lang.String.format;
77
import static java.util.Arrays.asList;
8-
import static java.util.Collections.emptyList;
98
import static java.util.Collections.singletonList;
109

1110
import com.datadog.debugger.agent.DebuggerAgent;
@@ -54,6 +53,13 @@ public void evaluate(
5453
}
5554

5655
super.evaluate(context, status, methodLocation);
56+
AgentSpan span = findSpan(AgentTracer.activeSpan());
57+
58+
if (span == null) {
59+
LOGGER.debug("Could not find the span for probeId {}", id);
60+
return;
61+
}
62+
applyCodeOriginTags(span);
5763
}
5864

5965
@Override
@@ -68,63 +74,53 @@ public void commit(
6874
LOGGER.debug("Could not find the span for probeId {}", id);
6975
return;
7076
}
71-
String snapshotId = null;
7277
DebuggerSink sink = DebuggerAgent.getSink();
7378
if (isDebuggerEnabled(span) && sink != null) {
7479
Snapshot snapshot = createSnapshot();
7580
if (fillSnapshot(entryContext, exitContext, caughtExceptions, snapshot)) {
76-
snapshotId = snapshot.getId();
81+
String snapshotId = snapshot.getId();
7782
LOGGER.debug("committing code origin probe id={}, snapshot id={}", id, snapshotId);
7883
commitSnapshot(snapshot, sink);
84+
85+
List<AgentSpan> agentSpans =
86+
entrySpanProbe ? asList(span, span.getLocalRootSpan()) : singletonList(span);
87+
for (AgentSpan agentSpan : agentSpans) {
88+
if (agentSpan.getTag(format(DD_CODE_ORIGIN_FRAME, 0, "snapshot_id")) == null) {
89+
agentSpan.setTag(format(DD_CODE_ORIGIN_FRAME, 0, "snapshot_id"), snapshotId);
90+
}
91+
}
7992
}
8093
}
81-
applySpanOriginTags(span, snapshotId);
8294
if (sink != null) {
8395
sink.getProbeStatusSink().addEmitting(probeId);
8496
}
8597
span.getLocalRootSpan().setTag(getId(), (String) null); // clear possible span reference
8698
}
8799

88-
private List<StackTraceElement> findLocation() {
89-
if (entrySpanProbe && stackTraceElements == null) {
90-
ProbeLocation probeLocation = getLocation();
91-
List<String> lines = probeLocation.getLines();
92-
int line = lines == null ? -1 : Integer.parseInt(lines.get(0));
93-
stackTraceElements =
94-
singletonList(
95-
new StackTraceElement(
96-
probeLocation.getType(),
97-
probeLocation.getMethod(),
98-
probeLocation.getFile(),
99-
line));
100-
}
101-
return stackTraceElements != null ? stackTraceElements : emptyList();
102-
}
103-
104-
private void applySpanOriginTags(AgentSpan span, String snapshotId) {
100+
private List<AgentSpan> applyCodeOriginTags(AgentSpan span) {
105101
List<StackTraceElement> entries =
106102
stackTraceElements != null ? stackTraceElements : getUserStackFrames();
107103
List<AgentSpan> agentSpans =
108104
entrySpanProbe ? asList(span, span.getLocalRootSpan()) : singletonList(span);
109105

110106
for (AgentSpan s : agentSpans) {
111-
s.setTag(DD_CODE_ORIGIN_TYPE, entrySpanProbe ? "entry" : "exit");
112-
113-
for (int i = 0; i < entries.size(); i++) {
114-
StackTraceElement info = entries.get(i);
115-
String fileName = info.getFileName();
116-
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "file"), fileName);
117-
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "method"), info.getMethodName());
118-
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "line"), info.getLineNumber());
119-
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "type"), info.getClassName());
120-
if (i == 0 && entrySpanProbe) {
121-
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "signature"), where.getSignature());
122-
}
123-
if (i == 0 && snapshotId != null) {
124-
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "snapshot_id"), snapshotId);
107+
if (s.getTag(DD_CODE_ORIGIN_TYPE) == null) {
108+
s.setTag(DD_CODE_ORIGIN_TYPE, entrySpanProbe ? "entry" : "exit");
109+
110+
for (int i = 0; i < entries.size(); i++) {
111+
StackTraceElement info = entries.get(i);
112+
String fileName = info.getFileName();
113+
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "file"), fileName);
114+
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "method"), info.getMethodName());
115+
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "line"), info.getLineNumber());
116+
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "type"), info.getClassName());
117+
if (i == 0 && entrySpanProbe) {
118+
s.setTag(format(DD_CODE_ORIGIN_FRAME, i, "signature"), where.getSignature());
119+
}
125120
}
126121
}
127122
}
123+
return agentSpans;
128124
}
129125

130126
public boolean entrySpanProbe() {

dd-java-agent/agent-debugger/src/test/java/com/datadog/debugger/origin/CodeOriginTest.java

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static datadog.trace.api.DDTags.DD_CODE_ORIGIN_PREFIX;
66
import static datadog.trace.api.DDTags.DD_CODE_ORIGIN_TYPE;
77
import static java.lang.String.format;
8+
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
89
import static java.util.Arrays.asList;
910
import static org.junit.jupiter.api.Assertions.assertEquals;
1011
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -31,8 +32,11 @@
3132
import datadog.trace.bootstrap.debugger.Limits;
3233
import datadog.trace.bootstrap.debugger.ProbeId;
3334
import datadog.trace.core.CoreTracer;
35+
import java.io.File;
3436
import java.io.IOException;
3537
import java.net.URISyntaxException;
38+
import java.nio.file.Files;
39+
import java.nio.file.Paths;
3640
import java.util.ArrayList;
3741
import java.util.HashSet;
3842
import java.util.List;
@@ -42,14 +46,19 @@
4246
import java.util.stream.Collectors;
4347
import org.jetbrains.annotations.NotNull;
4448
import org.joor.Reflect;
49+
import org.junit.jupiter.api.AfterAll;
4550
import org.junit.jupiter.api.BeforeEach;
4651
import org.junit.jupiter.api.Test;
4752

4853
public class CodeOriginTest extends CapturingTestBase {
4954

5055
private static final ProbeId CODE_ORIGIN_ID1 = new ProbeId("code origin 1", 0);
56+
5157
private static final ProbeId CODE_ORIGIN_ID2 = new ProbeId("code origin 2", 0);
5258

59+
private static final ProbeId CODE_ORIGIN_DOUBLE_ENTRY_ID =
60+
new ProbeId("double entry code origin", 0);
61+
5362
private static final int MAX_FRAMES = 20;
5463

5564
private DefaultCodeOriginRecorder codeOriginRecorder;
@@ -84,6 +93,27 @@ public void before() {
8493
setFieldInConfig(InstrumenterConfig.get(), "codeOriginEnabled", true);
8594
}
8695

96+
@AfterAll
97+
public static void collectClasses() throws IOException {
98+
File[] files =
99+
Paths.get(System.getProperty("java.io.tmpdir"), "debugger/com/datadog/debugger")
100+
.toFile()
101+
.listFiles(
102+
file -> {
103+
String name = file.getName();
104+
return name.startsWith("CodeOrigin") && name.endsWith(".class");
105+
});
106+
107+
if (new File("build").exists()) {
108+
File buildDir = new File("build/debugger");
109+
buildDir.mkdirs();
110+
for (File file : files) {
111+
Files.copy(
112+
file.toPath(), Paths.get(buildDir.getAbsolutePath(), file.getName()), REPLACE_EXISTING);
113+
}
114+
}
115+
}
116+
87117
@Test
88118
public void basicInstrumentation() throws Exception {
89119
final String className = "com.datadog.debugger.CodeOrigin01";
@@ -115,6 +145,30 @@ public void withLogProbe() throws IOException, URISyntaxException {
115145
checkResults(testClass, "debug_1", true);
116146
}
117147

148+
@Test
149+
public void doubleEntry() throws IOException, URISyntaxException {
150+
final String className = "com.datadog.debugger.CodeOrigin05";
151+
152+
List<LogProbe> probes =
153+
asList(
154+
new CodeOriginProbe(
155+
CODE_ORIGIN_ID1, true, Where.of(className, "entry", "()", "53"), MAX_FRAMES),
156+
new CodeOriginProbe(
157+
CODE_ORIGIN_ID2, false, Where.of(className, "exit", "()", "62"), MAX_FRAMES),
158+
new CodeOriginProbe(
159+
CODE_ORIGIN_DOUBLE_ENTRY_ID,
160+
true,
161+
Where.of(className, "doubleEntry", "()", "66"),
162+
MAX_FRAMES));
163+
installProbes(probes);
164+
final Class<?> testClass = compileAndLoadClass(className);
165+
checkResults(testClass, "fullTrace", false);
166+
List<? extends MutableSpan> trace = traceInterceptor.getTrace();
167+
MutableSpan span = trace.get(0);
168+
// this should be entry but until we get the ordering resolved, it's this.
169+
assertEquals("doubleEntry", span.getTag(format(DD_CODE_ORIGIN_FRAME, 0, "method")));
170+
}
171+
118172
@Test
119173
public void stackDepth() throws IOException, URISyntaxException {
120174
final String CLASS_NAME = "com.datadog.debugger.CodeOrigin04";
@@ -192,7 +246,6 @@ private List<LogProbe> codeOriginProbes(String type) {
192246
}
193247

194248
private void checkResults(Class<?> testClass, String parameter, boolean includeSnapshot) {
195-
Reflect.onClass(testClass).call("main", parameter).get();
196249
int result = Reflect.onClass(testClass).call("main", parameter).get();
197250
assertEquals(0, result);
198251
List<? extends MutableSpan> spans = traceInterceptor.getTrace();
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package com.datadog.debugger;
2+
3+
import datadog.trace.bootstrap.debugger.spanorigin.CodeOriginInfo;
4+
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
5+
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
6+
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
7+
import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI;
8+
import datadog.trace.bootstrap.instrumentation.api.ScopeSource;
9+
import datadog.trace.core.DDSpan;
10+
11+
public class CodeOrigin05 {
12+
private int intField = 42;
13+
14+
private static TracerAPI tracerAPI = AgentTracer.get();
15+
16+
public static int main(String arg) throws ReflectiveOperationException {
17+
AgentSpan span = newSpan("main");
18+
AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL);
19+
if (arg.equals("debug_1")) {
20+
((DDSpan) span.getLocalRootSpan()).setTag("_dd.p.debug", "1");
21+
} else if (arg.equals("debug_0")) {
22+
((DDSpan) span.getLocalRootSpan()).setTag("_dd.p.debug", "0");
23+
}
24+
25+
fullTrace();
26+
27+
span.finish();
28+
scope.close();
29+
30+
return 0;
31+
}
32+
33+
private static void fullTrace() throws NoSuchMethodException {
34+
AgentSpan span = newSpan("entry");
35+
AgentScope scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL);
36+
entry();
37+
span.finish();
38+
scope.close();
39+
40+
span = newSpan("exit");
41+
scope = tracerAPI.activateSpan(span, ScopeSource.MANUAL);
42+
exit();
43+
span.finish();
44+
scope.close();
45+
}
46+
47+
private static AgentSpan newSpan(String name) {
48+
return tracerAPI.buildSpan("code origin tests", name).start();
49+
}
50+
51+
public static void entry() throws NoSuchMethodException {
52+
// just to fill out the method body
53+
boolean dummyCode = true;
54+
if (!dummyCode) {
55+
dummyCode = false;
56+
}
57+
doubleEntry();
58+
}
59+
60+
private static void exit() {
61+
int x = 47 / 3;
62+
}
63+
64+
public static void doubleEntry() throws NoSuchMethodException {
65+
// just to fill out the method body
66+
boolean dummyCode = true;
67+
if (!dummyCode) {
68+
dummyCode = false;
69+
}
70+
}
71+
72+
}

0 commit comments

Comments
 (0)