Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the DebuggerProbe #7460

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ public interface ExceptionDebugger {
void handleException(Throwable t, AgentSpan span);
}

public interface SpanDebugger {
String captureSnapshot(String signature);
public interface CodeOriginRecorder {
String captureCodeOrigin(String signature);
}

private static volatile ProbeResolver probeResolver;
Expand All @@ -77,7 +77,7 @@ public interface SpanDebugger {
private static volatile Tracer tracer;
private static volatile ValueSerializer valueSerializer;
private static volatile ExceptionDebugger exceptionDebugger;
private static volatile SpanDebugger spanDebugger;
private static volatile CodeOriginRecorder codeOriginRecorder;

public static void initProbeResolver(ProbeResolver probeResolver) {
DebuggerContext.probeResolver = probeResolver;
Expand All @@ -103,8 +103,8 @@ public static void initExceptionDebugger(ExceptionDebugger exceptionDebugger) {
DebuggerContext.exceptionDebugger = exceptionDebugger;
}

public static void initSpanDebugger(SpanDebugger spanDebugger) {
DebuggerContext.spanDebugger = spanDebugger;
public static void initCodeOrigin(CodeOriginRecorder codeOriginRecorder) {
DebuggerContext.codeOriginRecorder = codeOriginRecorder;
}

/**
Expand Down Expand Up @@ -342,14 +342,14 @@ public static void commit(
}
}

public static String captureSnapshot(String signature) {
public static String captureCodeOrigin(String signature) {
try {
SpanDebugger debugger = spanDebugger;
if (debugger != null) {
return debugger.captureSnapshot(signature);
CodeOriginRecorder recorder = codeOriginRecorder;
if (recorder != null) {
return recorder.captureCodeOrigin(signature);
}
} catch (Exception ex) {
LOGGER.debug("Error in addSnapshot: ", ex);
LOGGER.debug("Error in captureCodeOrigin: ", ex);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
package datadog.trace.bootstrap.debugger.spanorigin;

import static datadog.trace.bootstrap.debugger.DebuggerContext.captureSnapshot;
import static datadog.trace.bootstrap.debugger.DebuggerContext.captureCodeOrigin;
import static java.util.Arrays.stream;

import datadog.trace.api.InstrumenterConfig;
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
import java.lang.reflect.Method;
import java.util.stream.Collectors;

public class SpanOriginInfo {
public static void entry(AgentSpan span, Method method) {
if (InstrumenterConfig.get().isSpanOriginEnabled()) {
public class CodeOriginInfo {
public static void entry(Method method) {
if (InstrumenterConfig.get().isCodeOriginEnabled()) {
String signature =
stream(method.getParameterTypes())
.map(Class::getName)
.collect(Collectors.joining(",", "(", ")"));
captureSnapshot(signature);
captureCodeOrigin(signature);
}
}

public static void exit(AgentSpan span) {
if (InstrumenterConfig.get().isSpanOriginEnabled()) {
span.getLocalRootSpan().setMetaStruct(captureSnapshot(null), span);
public static void exit() {
if (InstrumenterConfig.get().isCodeOriginEnabled()) {
captureCodeOrigin(null);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.datadog.debugger.agent;

import com.datadog.debugger.probe.DebuggerProbe;
import com.datadog.debugger.probe.ExceptionProbe;
import com.datadog.debugger.probe.LogProbe;
import com.datadog.debugger.probe.MetricProbe;
Expand Down Expand Up @@ -65,6 +66,7 @@ public int hashCode() {
private final Collection<MetricProbe> metricProbes;
private final Collection<LogProbe> logProbes;
private final Collection<SpanProbe> spanProbes;
private final Collection<DebuggerProbe> debuggerProbes;
private final Collection<SpanDecorationProbe> spanDecorationProbes;
private final FilterList allowList;
private final FilterList denyList;
Expand All @@ -79,14 +81,15 @@ public Configuration(
Collection<MetricProbe> metricProbes,
Collection<LogProbe> logProbes,
Collection<SpanProbe> spanProbes) {
this(serviceName, metricProbes, logProbes, spanProbes, null, null, null, null);
this(serviceName, metricProbes, logProbes, spanProbes, null, null, null, null, null);
}

public Configuration(
String serviceName,
Collection<MetricProbe> metricProbes,
Collection<LogProbe> logProbes,
Collection<SpanProbe> spanProbes,
Collection<DebuggerProbe> debuggerProbes,
Collection<SpanDecorationProbe> spanDecorationProbes,
FilterList allowList,
FilterList denyList,
Expand All @@ -95,6 +98,7 @@ public Configuration(
this.metricProbes = metricProbes;
this.logProbes = logProbes;
this.spanProbes = spanProbes;
this.debuggerProbes = debuggerProbes;
this.spanDecorationProbes = spanDecorationProbes;
this.allowList = allowList;
this.denyList = denyList;
Expand All @@ -117,6 +121,10 @@ public Collection<SpanProbe> getSpanProbes() {
return spanProbes;
}

public Collection<DebuggerProbe> getDebuggerProbes() {
return debuggerProbes;
}

public Collection<SpanDecorationProbe> getSpanDecorationProbes() {
return spanDecorationProbes;
}
Expand All @@ -135,6 +143,9 @@ public LogProbe.Sampling getSampling() {

public Collection<ProbeDefinition> getDefinitions() {
Collection<ProbeDefinition> result = new ArrayList<>();
if (debuggerProbes != null) {
result.addAll(debuggerProbes);
}
if (metricProbes != null) {
result.addAll(metricProbes);
}
Expand Down Expand Up @@ -198,6 +209,7 @@ public static class Builder {
private List<MetricProbe> metricProbes = null;
private List<LogProbe> logProbes = null;
private List<SpanProbe> spanProbes = null;
private List<DebuggerProbe> debuggerProbes = null;
private List<SpanDecorationProbe> spanDecorationProbes = null;
private FilterList allowList = null;
private FilterList denyList = null;
Expand All @@ -214,6 +226,7 @@ public Configuration.Builder add(Collection<? extends ProbeDefinition> definitio
}
for (ProbeDefinition definition : definitions) {
if (definition instanceof MetricProbe) add((MetricProbe) definition);
if (definition instanceof DebuggerProbe) add((DebuggerProbe) definition);
evanchooly marked this conversation as resolved.
Show resolved Hide resolved
if (definition instanceof LogProbe) add((LogProbe) definition);
if (definition instanceof SpanProbe) add((SpanProbe) definition);
if (definition instanceof SpanDecorationProbe) add((SpanDecorationProbe) definition);
Expand Down Expand Up @@ -245,6 +258,14 @@ public Configuration.Builder add(SpanProbe probe) {
return this;
}

public Configuration.Builder add(DebuggerProbe probe) {
if (debuggerProbes == null) {
debuggerProbes = new ArrayList<>();
}
debuggerProbes.add(probe);
return this;
}

public Configuration.Builder add(SpanDecorationProbe probe) {
if (spanDecorationProbes == null) {
spanDecorationProbes = new ArrayList<>();
Expand Down Expand Up @@ -300,6 +321,16 @@ public Configuration.Builder addSpanProbes(Collection<SpanProbe> probes) {
return this;
}

public Configuration.Builder addDebuggerProbes(Collection<DebuggerProbe> probes) {
if (probes == null) {
return this;
}
for (DebuggerProbe probe : probes) {
add(probe);
}
return this;
}

public Configuration.Builder addSpanDecorationProbes(Collection<SpanDecorationProbe> probes) {
if (probes == null) {
return this;
Expand Down Expand Up @@ -346,6 +377,7 @@ public Configuration.Builder add(Configuration other) {
addMetricProbes(other.getMetricProbes());
addLogProbes(other.getLogProbes());
addSpanProbes(other.getSpanProbes());
addDebuggerProbes(other.getDebuggerProbes());
addSpanDecorationProbes(other.getSpanDecorationProbes());
addAllowList(other.getAllowList());
addDenyList(other.getDenyList());
Expand All @@ -359,6 +391,7 @@ public Configuration build() {
metricProbes,
logProbes,
spanProbes,
debuggerProbes,
spanDecorationProbes,
allowList,
denyList,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
import static com.datadog.debugger.agent.ConfigurationAcceptor.Source.REMOTE_CONFIG;
import static datadog.trace.util.AgentThreadFactory.AGENT_THREAD_GROUP;

import com.datadog.debugger.codeorigin.CodeOriginProbeManager;
import com.datadog.debugger.codeorigin.DefaultCodeOriginRecorder;
import com.datadog.debugger.exception.DefaultExceptionDebugger;
import com.datadog.debugger.exception.ExceptionProbeManager;
import com.datadog.debugger.sink.DebuggerSink;
import com.datadog.debugger.sink.ProbeStatusSink;
import com.datadog.debugger.sink.SnapshotSink;
import com.datadog.debugger.sink.SymbolSink;
import com.datadog.debugger.snapshot.DefaultSpanDebugger;
import com.datadog.debugger.symbol.SymDBEnablement;
import com.datadog.debugger.symbol.SymbolAggregator;
import com.datadog.debugger.uploader.BatchUploader;
Expand Down Expand Up @@ -102,9 +103,10 @@ public static synchronized void run(
config.getDebuggerMaxExceptionPerSecond());
DebuggerContext.initExceptionDebugger(defaultExceptionDebugger);
}
if (config.isDebuggerSpanDebugEnabled()) {
DebuggerContext.initSpanDebugger(
new DefaultSpanDebugger(configurationUpdater, classNameFiltering));
if (config.isDebuggerCodeOriginEnabled()) {
DebuggerContext.initCodeOrigin(
new DefaultCodeOriginRecorder(
new CodeOriginProbeManager(configurationUpdater, classNameFiltering)));
}
if (config.isDebuggerInstrumentTheWorld()) {
setupInstrumentTheWorldTransformer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static com.datadog.debugger.agent.ConfigurationAcceptor.Source.REMOTE_CONFIG;

import com.datadog.debugger.probe.DebuggerProbe;
import com.datadog.debugger.probe.LogProbe;
import com.datadog.debugger.probe.MetricProbe;
import com.datadog.debugger.probe.ProbeDefinition;
Expand All @@ -28,13 +29,15 @@
import org.slf4j.LoggerFactory;

public class DebuggerProductChangesListener implements ProductListener {
public static final int MAX_ALLOWED_DEBUGGER_PROBES = 100;
public static final int MAX_ALLOWED_METRIC_PROBES = 100;
public static final int MAX_ALLOWED_LOG_PROBES = 100;
public static final int MAX_ALLOWED_SPAN_PROBES = 100;
public static final int MAX_ALLOWED_SPAN_DECORATION_PROBES = 100;
public static final String LOG_PROBE_PREFIX = "logProbe_";
public static final String METRIC_PROBE_PREFIX = "metricProbe_";
public static final String SPAN_PROBE_PREFIX = "spanProbe_";
public static final String DEBUGGER_PROBE_PREFIX = "debuggerProbe_";
public static final String SPAN_DECORATION_PROBE_PREFIX = "spanDecorationProbe_";
private static final Logger LOGGER =
LoggerFactory.getLogger(DebuggerProductChangesListener.class);
Expand All @@ -52,6 +55,9 @@ static class Adapter {
static final JsonAdapter<SpanProbe> SPAN_PROBE_JSON_ADAPTER =
MoshiHelper.createMoshiConfig().adapter(SpanProbe.class);

static final JsonAdapter<DebuggerProbe> DEBUGGER_PROBE_JSON_ADAPTER =
MoshiHelper.createMoshiConfig().adapter(DebuggerProbe.class);

static final JsonAdapter<SpanDecorationProbe> SPAN_DECORATION_PROBE_JSON_ADAPTER =
MoshiHelper.createMoshiConfig().adapter(SpanDecorationProbe.class);

Expand All @@ -71,6 +77,10 @@ static SpanProbe deserializeSpanProbe(byte[] content) throws IOException {
return deserialize(SPAN_PROBE_JSON_ADAPTER, content);
}

static DebuggerProbe deserializeDebuggerProbe(byte[] content) throws IOException {
return deserialize(DEBUGGER_PROBE_JSON_ADAPTER, content);
}

static SpanDecorationProbe deserializeSpanDecorationProbe(byte[] content) throws IOException {
return deserialize(SPAN_DECORATION_PROBE_JSON_ADAPTER, content);
}
Expand Down Expand Up @@ -108,6 +118,9 @@ public void accept(ConfigKey configKey, byte[] content, PollingRateHinter pollin
} else if (configId.startsWith(SPAN_PROBE_PREFIX)) {
SpanProbe spanProbe = Adapter.deserializeSpanProbe(content);
configChunks.put(configId, definitions -> definitions.add(spanProbe));
} else if (configId.startsWith(DEBUGGER_PROBE_PREFIX)) {
DebuggerProbe debuggerProbe = Adapter.deserializeDebuggerProbe(content);
configChunks.put(configId, definitions -> definitions.add(debuggerProbe));
} else if (configId.startsWith(SPAN_DECORATION_PROBE_PREFIX)) {
SpanDecorationProbe spanDecorationProbe = Adapter.deserializeSpanDecorationProbe(content);
configChunks.put(configId, definitions -> definitions.add(spanDecorationProbe));
Expand Down Expand Up @@ -148,6 +161,7 @@ public void commit(PollingRateHinter pollingRateHinter) {

static class DefinitionBuilder {
private final Collection<ProbeDefinition> definitions = new ArrayList<>();
private int debuggerProbeCount = 0;
evanchooly marked this conversation as resolved.
Show resolved Hide resolved
private int metricProbeCount = 0;
private int logProbeCount = 0;
private int spanProbeCount = 0;
Expand Down Expand Up @@ -180,6 +194,15 @@ void add(SpanProbe probe) {
spanProbeCount++;
}

void add(DebuggerProbe probe) {
if (debuggerProbeCount >= MAX_ALLOWED_DEBUGGER_PROBES) {
LOGGER.debug("Max allowed debugger probes reached, ignoring new probe: {}", probe);
return;
}
definitions.add(probe);
debuggerProbeCount++;
}

void add(SpanDecorationProbe probe) {
if (spanDecorationProbeCount >= MAX_ALLOWED_SPAN_DECORATION_PROBES) {
LOGGER.debug("Max allowed span decoration probes reached, ignoring new probe: {}", probe);
Expand All @@ -197,6 +220,8 @@ void addAll(Collection<ProbeDefinition> newDefinitions) {
add((LogProbe) definition);
} else if (definition instanceof SpanProbe) {
add((SpanProbe) definition);
} else if (definition instanceof DebuggerProbe) {
add((DebuggerProbe) definition);
} else if (definition instanceof SpanDecorationProbe) {
add((SpanDecorationProbe) definition);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.datadog.debugger.instrumentation.DiagnosticMessage;
import com.datadog.debugger.instrumentation.InstrumentationResult;
import com.datadog.debugger.instrumentation.MethodInfo;
import com.datadog.debugger.probe.DebuggerProbe;
import com.datadog.debugger.probe.ExceptionProbe;
import com.datadog.debugger.probe.ForceMethodInstrumentation;
import com.datadog.debugger.probe.LogProbe;
Expand Down Expand Up @@ -77,7 +78,12 @@ public class DebuggerTransformer implements ClassFileTransformer {
private static final String CANNOT_FIND_LINE = "No executable code was found at %s:L%s";
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
private static final List<Class<?>> PROBE_ORDER =
Arrays.asList(MetricProbe.class, LogProbe.class, SpanDecorationProbe.class, SpanProbe.class);
Arrays.asList(
DebuggerProbe.class,
MetricProbe.class,
LogProbe.class,
SpanDecorationProbe.class,
SpanProbe.class);
private static final String JAVA_IO_TMPDIR = "java.io.tmpdir";

private final Config config;
Expand Down Expand Up @@ -212,7 +218,7 @@ private Map<Where, List<ProbeDefinition>> mergeLocations(
Map<Where, List<ProbeDefinition>> mergedProbes = new HashMap<>();
for (ProbeDefinition definition : definitions) {
Where where = definition.getWhere();
if (definition instanceof ExceptionProbe) {
if (definition instanceof ForceMethodInstrumentation) {
// normalize where for line => to precise method location
where = Where.convertLineToMethod(definition.getWhere(), classFileLines);
}
Expand Down Expand Up @@ -411,7 +417,7 @@ private void verifyByteCode(String classFilePath, byte[] classFile) {
if (!result.isEmpty()) {
log.warn("Verification of instrumented class {} failed", classFilePath);
log.debug("Verify result: {}", stringWriter);
throw new RuntimeException("Generated bydecode is invalid for " + classFilePath);
throw new RuntimeException("Generated bytecode is invalid for " + classFilePath);
}
}

Expand Down
Loading
Loading