Skip to content

Commit d2e70dc

Browse files
committed
Enhance log probes to honor debug session tags
1 parent 0b1e6ff commit d2e70dc

File tree

6 files changed

+228
-30
lines changed

6 files changed

+228
-30
lines changed

dd-java-agent/agent-debugger/debugger-bootstrap/src/main/java/datadog/trace/bootstrap/debugger/DebuggerContext.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,26 @@ public class DebuggerContext {
2121
private static final ThreadLocal<Boolean> IN_PROBE = ThreadLocal.withInitial(() -> Boolean.FALSE);
2222

2323
public enum SkipCause {
24-
RATE,
25-
CONDITION
24+
RATE {
25+
@Override
26+
public String tag() {
27+
return "cause:rate";
28+
}
29+
},
30+
CONDITION {
31+
@Override
32+
public String tag() {
33+
return "cause:condition";
34+
}
35+
},
36+
DEBUG_SESSION_DISABLED {
37+
@Override
38+
public String tag() {
39+
return "cause:debug session disabled";
40+
}
41+
};
42+
43+
public abstract String tag();
2644
}
2745

2846
public interface ProbeResolver {

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

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.util.Arrays;
4141
import java.util.Collections;
4242
import java.util.List;
43+
import java.util.Map;
4344
import java.util.Objects;
4445
import java.util.function.Consumer;
4546
import org.slf4j.Logger;
@@ -434,7 +435,8 @@ public void evaluate(
434435
// sample when no condition associated
435436
sample(logStatus, methodLocation);
436437
}
437-
logStatus.setCondition(evaluateCondition(context, logStatus));
438+
logStatus.setCondition(
439+
!logStatus.getDebugSessionStatus().isDisabled() && evaluateCondition(context, logStatus));
438440
CapturedContext.CapturedThrowable throwable = context.getCapturedThrowable();
439441
if (logStatus.hasConditionErrors() && throwable != null) {
440442
logStatus.addError(
@@ -503,10 +505,16 @@ private void sample(LogStatus logStatus, MethodLocation methodLocation) {
503505
if (!MethodLocation.isSame(methodLocation, evaluateAt)) {
504506
return;
505507
}
506-
boolean sampled = ProbeRateLimiter.tryProbe(id);
508+
boolean sampled =
509+
!logStatus.getDebugSessionStatus().isDisabled() && ProbeRateLimiter.tryProbe(id);
507510
logStatus.setSampled(sampled);
508511
if (!sampled) {
509-
DebuggerAgent.getSink().skipSnapshot(id, DebuggerContext.SkipCause.RATE);
512+
DebuggerAgent.getSink()
513+
.skipSnapshot(
514+
id,
515+
logStatus.getDebugSessionStatus().isDisabled()
516+
? DebuggerContext.SkipCause.DEBUG_SESSION_DISABLED
517+
: DebuggerContext.SkipCause.RATE);
510518
}
511519
}
512520

@@ -685,6 +693,7 @@ public static class LogStatus extends CapturedContext.Status {
685693
new LogStatus(ProbeImplementation.UNKNOWN, true);
686694

687695
private boolean condition = true;
696+
private final DebugSessionStatus debugSessionStatus;
688697
private boolean hasLogTemplateErrors;
689698
private boolean hasConditionErrors;
690699
private boolean sampled = true;
@@ -693,10 +702,11 @@ public static class LogStatus extends CapturedContext.Status {
693702

694703
public LogStatus(ProbeImplementation probeImplementation) {
695704
super(probeImplementation);
705+
debugSessionStatus = debugSessionStatus();
696706
}
697707

698708
private LogStatus(ProbeImplementation probeImplementation, boolean condition) {
699-
super(probeImplementation);
709+
this(probeImplementation);
700710
this.condition = condition;
701711
}
702712

@@ -722,6 +732,26 @@ public boolean getCondition() {
722732
return condition;
723733
}
724734

735+
public DebugSessionStatus getDebugSessionStatus() {
736+
return debugSessionStatus;
737+
}
738+
739+
private DebugSessionStatus debugSessionStatus() {
740+
if (probeImplementation instanceof ProbeDefinition) {
741+
ProbeDefinition definition = (ProbeDefinition) probeImplementation;
742+
Map<String, String> sessions = getDebugSessions();
743+
String sessionId = definition.getDebugSessionId();
744+
if (sessionId == null) {
745+
return DebugSessionStatus.NONE;
746+
}
747+
return "1".equals(sessions.get(sessionId)) || "1".equals(sessions.get("*"))
748+
? DebugSessionStatus.ACTIVE
749+
: DebugSessionStatus.DISABLED;
750+
}
751+
752+
return DebugSessionStatus.NONE;
753+
}
754+
725755
public void setCondition(boolean value) {
726756
this.condition = value;
727757
}
@@ -765,6 +795,29 @@ public boolean isForceSampling() {
765795
public void setForceSampling(boolean forceSampling) {
766796
this.forceSampling = forceSampling;
767797
}
798+
799+
@Override
800+
public String toString() {
801+
return "LogStatus{"
802+
+ ", probeId="
803+
+ probeImplementation.getId()
804+
+ ", condition="
805+
+ condition
806+
+ ", debugSessionStatus="
807+
+ debugSessionStatus
808+
+ ", forceSampling="
809+
+ forceSampling
810+
+ ", hasConditionErrors="
811+
+ hasConditionErrors
812+
+ ", hasLogTemplateErrors="
813+
+ hasLogTemplateErrors
814+
+ ", message='"
815+
+ message
816+
+ '\''
817+
+ ", sampled="
818+
+ sampled
819+
+ '}';
820+
}
768821
}
769822

770823
@Generated

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

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
import datadog.trace.bootstrap.debugger.ProbeId;
1313
import datadog.trace.bootstrap.debugger.ProbeImplementation;
1414
import datadog.trace.bootstrap.debugger.ProbeLocation;
15+
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
16+
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
17+
import datadog.trace.bootstrap.instrumentation.api.AgentTracer.TracerAPI;
18+
import datadog.trace.core.DDSpan;
19+
import datadog.trace.core.DDSpanContext;
1520
import java.io.IOException;
1621
import java.util.ArrayList;
1722
import java.util.Arrays;
@@ -26,7 +31,7 @@ public abstract class ProbeDefinition implements ProbeImplementation {
2631
protected static final String LANGUAGE = "java";
2732

2833
protected final String language;
29-
protected final String id;
34+
protected String id;
3035
protected final int version;
3136
protected transient ProbeId probeId;
3237
protected final Tag[] tags;
@@ -54,6 +59,9 @@ protected ProbeDefinition(
5459

5560
@Override
5661
public String getId() {
62+
if (id == null) {
63+
id = probeId != null ? probeId.getId() : null;
64+
}
5765
return id;
5866
}
5967

@@ -93,6 +101,9 @@ public String concatTags() {
93101
}
94102

95103
public Map<String, String> getTagMap() {
104+
if (tagMap.isEmpty() && tags != null) {
105+
initTagMap(tagMap, tags);
106+
}
96107
return Collections.unmodifiableMap(tagMap);
97108
}
98109

@@ -136,6 +147,10 @@ public ProbeLocation getLocation() {
136147
public void evaluate(
137148
CapturedContext context, CapturedContext.Status status, MethodLocation methodLocation) {}
138149

150+
protected String getDebugSessionId() {
151+
return getTagMap().get("sessionId");
152+
}
153+
139154
@Override
140155
public void commit(
141156
CapturedContext entryContext,
@@ -166,6 +181,16 @@ public boolean isLineProbe() {
166181
return sourceLines != null && sourceLines.length > 0;
167182
}
168183

184+
public enum DebugSessionStatus {
185+
NONE,
186+
ACTIVE,
187+
DISABLED;
188+
189+
public boolean isDisabled() {
190+
return this == DISABLED;
191+
}
192+
}
193+
169194
public abstract static class Builder<T extends Builder> {
170195
protected String language = LANGUAGE;
171196
protected ProbeId probeId;
@@ -360,4 +385,28 @@ public void toJson(JsonWriter jsonWriter, Tag[] tags) throws IOException {
360385
jsonWriter.endArray();
361386
}
362387
}
388+
389+
public static Map<String, String> getDebugSessions() {
390+
HashMap<String, String> sessions = new HashMap<>();
391+
TracerAPI tracer = AgentTracer.get();
392+
if (tracer != null) {
393+
AgentSpan span = tracer.activeSpan();
394+
if (span instanceof DDSpan) {
395+
DDSpanContext context = (DDSpanContext) span.context();
396+
String debug = context.getPropagationTags().getDebugPropagation();
397+
if (debug != null) {
398+
String[] entries = debug.split(",");
399+
for (String entry : entries) {
400+
if (!entry.contains(":")) {
401+
sessions.put("*", entry);
402+
} else {
403+
String[] values = entry.split(":");
404+
sessions.put(values[0], values[1]);
405+
}
406+
}
407+
}
408+
}
409+
}
410+
return sessions;
411+
}
363412
}

dd-java-agent/agent-debugger/src/main/java/com/datadog/debugger/sink/DebuggerSink.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import com.datadog.debugger.uploader.BatchUploader;
55
import com.datadog.debugger.util.DebuggerMetrics;
66
import datadog.trace.api.Config;
7-
import datadog.trace.bootstrap.debugger.DebuggerContext;
7+
import datadog.trace.bootstrap.debugger.DebuggerContext.SkipCause;
88
import datadog.trace.bootstrap.debugger.ProbeId;
99
import datadog.trace.util.AgentTaskScheduler;
1010
import java.util.List;
@@ -223,20 +223,8 @@ private void reportError(ProbeId probeId, DiagnosticMessage msg) {
223223
}
224224

225225
/** Notifies the snapshot was skipped for one of the SkipCause reason */
226-
public void skipSnapshot(String probeId, DebuggerContext.SkipCause cause) {
227-
String causeTag;
228-
switch (cause) {
229-
case RATE:
230-
causeTag = "cause:rate";
231-
break;
232-
case CONDITION:
233-
causeTag = "cause:condition";
234-
break;
235-
default:
236-
throw new IllegalArgumentException("Unknown cause: " + cause);
237-
}
238-
String probeIdTag = "probe_id:" + probeId;
239-
debuggerMetrics.incrementCounter(PREFIX + "skip", causeTag, probeIdTag);
226+
public void skipSnapshot(String probeId, SkipCause cause) {
227+
debuggerMetrics.incrementCounter(PREFIX + "skip", cause.tag(), "probe_id:" + probeId);
240228
}
241229

242230
long getCurrentLowRateFlushInterval() {

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

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -352,14 +352,7 @@ public static LogProbe.Builder createProbeBuilder(
352352
protected TestSnapshotListener installProbes(
353353
Configuration configuration, ProbeDefinition... probes) {
354354

355-
config = mock(Config.class);
356-
when(config.isDebuggerEnabled()).thenReturn(true);
357-
when(config.isDebuggerClassFileDumpEnabled()).thenReturn(true);
358-
when(config.isDebuggerVerifyByteCode()).thenReturn(false);
359-
when(config.getFinalDebuggerSnapshotUrl())
360-
.thenReturn("http://localhost:8126/debugger/v1/input");
361-
when(config.getFinalDebuggerSymDBUrl()).thenReturn("http://localhost:8126/symdb/v1/input");
362-
when(config.getDebuggerCodeOriginMaxUserFrames()).thenReturn(20);
355+
config = mockConfig();
363356
instrumentationListener = new MockInstrumentationListener();
364357
probeStatusSink = mock(ProbeStatusSink.class);
365358

@@ -404,6 +397,19 @@ protected TestSnapshotListener installProbes(
404397
return listener;
405398
}
406399

400+
public static Config mockConfig() {
401+
Config config = mock(Config.class);
402+
when(config.isDebuggerEnabled()).thenReturn(true);
403+
when(config.isDebuggerClassFileDumpEnabled()).thenReturn(true);
404+
when(config.isDebuggerVerifyByteCode()).thenReturn(false);
405+
when(config.getFinalDebuggerSnapshotUrl())
406+
.thenReturn("http://localhost:8126/debugger/v1/input");
407+
when(config.getFinalDebuggerSymDBUrl()).thenReturn("http://localhost:8126/symdb/v1/input");
408+
when(config.getDebuggerCodeOriginMaxUserFrames()).thenReturn(20);
409+
410+
return config;
411+
}
412+
407413
public static ProbeImplementation resolver(
408414
String encodedId,
409415
Collection<LogProbe> logProbes,

0 commit comments

Comments
 (0)