Skip to content

Commit b02d04d

Browse files
adapt ddprof context integration to use Stateful, simplify ScopeStack, introduce TimelineEvent
1 parent ea1cb06 commit b02d04d

10 files changed

Lines changed: 131 additions & 99 deletions

File tree

dd-java-agent/agent-profiling/profiling-controller-jfr/src/main/resources/jfr/dd.jfp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,5 @@ datadog.ExceptionSample#enabled=true
248248
datadog.ExceptionCount#enabled=true
249249
datadog.ProfilerSetting#enabled=true
250250
datadog.ContextInterval#enabled=true
251+
datadog.Timeline#enabled=true
252+
datadog.Timeline#threshold=10 ms
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.datadog.profiling.controller.openjdk;
2+
3+
import com.datadog.profiling.controller.openjdk.events.TimelineEvent;
4+
import datadog.trace.api.Stateful;
5+
import datadog.trace.bootstrap.instrumentation.api.ProfilerContext;
6+
import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration;
7+
8+
public class JFREventContextIntegration implements ProfilingContextIntegration {
9+
10+
@Override
11+
public Stateful newScopeState(ProfilerContext profilerContext) {
12+
return new TimelineEvent(
13+
profilerContext.getRootSpanId(),
14+
profilerContext.getSpanId(),
15+
String.valueOf(profilerContext.getOperationName()));
16+
}
17+
18+
@Override
19+
public String name() {
20+
return "jfr";
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.datadog.profiling.controller.openjdk.events;
2+
3+
import datadog.trace.api.Stateful;
4+
import jdk.jfr.Category;
5+
import jdk.jfr.Description;
6+
import jdk.jfr.Event;
7+
import jdk.jfr.Label;
8+
import jdk.jfr.Name;
9+
import jdk.jfr.StackTrace;
10+
11+
@Name("datadog.Timeline")
12+
@Label("Profiler Timeline Event")
13+
@Description("Datadog profiler timeline event")
14+
@Category("Datadog")
15+
@StackTrace(false)
16+
public class TimelineEvent extends Event implements Stateful {
17+
18+
@Label("Local Root Span Id")
19+
private final long localRootSpanId;
20+
21+
@Label("Span Id")
22+
private final long spanId;
23+
24+
@Label("Span Name")
25+
@Name("_dd.trace.operation")
26+
private final String operation;
27+
28+
public TimelineEvent(long localRootSpanId, long spanId, String operation) {
29+
this.localRootSpanId = localRootSpanId;
30+
this.spanId = spanId;
31+
this.operation = operation;
32+
begin();
33+
}
34+
35+
@Override
36+
public void close() {
37+
end();
38+
if (shouldCommit()) {
39+
commit();
40+
}
41+
}
42+
43+
@Override
44+
public void activate(Object context) {
45+
// nothing to do, either we get an event or we don't
46+
}
47+
}

dd-java-agent/agent-profiling/profiling-ddprof/src/main/java/com/datadog/profiling/ddprof/DatadogProfilingIntegration.java

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.datadog.profiling.ddprof;
22

3+
import datadog.trace.api.Stateful;
34
import datadog.trace.api.profiling.ProfilingContextAttribute;
45
import datadog.trace.api.profiling.ProfilingScope;
56
import datadog.trace.bootstrap.instrumentation.api.ProfilerContext;
@@ -17,6 +18,29 @@ public class DatadogProfilingIntegration implements ProfilingContextIntegration
1718
private static final boolean WALLCLOCK_ENABLED =
1819
DatadogProfilerConfig.isWallClockProfilerEnabled();
1920

21+
private final Stateful contextManager =
22+
new Stateful() {
23+
@Override
24+
public void close() {
25+
// this implementation is stateless so nothing to do here
26+
}
27+
28+
@Override
29+
public void activate(Object context) {
30+
if (context instanceof ProfilerContext) {
31+
ProfilerContext profilerContext = (ProfilerContext) context;
32+
DDPROF.setSpanContext(profilerContext.getSpanId(), profilerContext.getRootSpanId());
33+
DDPROF.setContextValue(SPAN_NAME_INDEX, profilerContext.getEncodedOperationName());
34+
DDPROF.setContextValue(RESOURCE_NAME_INDEX, profilerContext.getEncodedResourceName());
35+
}
36+
}
37+
};
38+
39+
@Override
40+
public Stateful newScopeState(ProfilerContext profilerContext) {
41+
return contextManager;
42+
}
43+
2044
@Override
2145
public void onAttach() {
2246
if (WALLCLOCK_ENABLED) {
@@ -26,6 +50,7 @@ public void onAttach() {
2650

2751
@Override
2852
public void onDetach() {
53+
clearContext();
2954
if (WALLCLOCK_ENABLED) {
3055
DDPROF.removeThread();
3156
}
@@ -57,25 +82,12 @@ public String name() {
5782
return "ddprof";
5883
}
5984

60-
@Override
61-
public void setContext(ProfilerContext profilerContext) {
62-
DDPROF.setSpanContext(profilerContext.getSpanId(), profilerContext.getRootSpanId());
63-
DDPROF.setContextValue(SPAN_NAME_INDEX, profilerContext.getEncodedOperationName());
64-
DDPROF.setContextValue(RESOURCE_NAME_INDEX, profilerContext.getEncodedResourceName());
65-
}
66-
67-
@Override
6885
public void clearContext() {
6986
DDPROF.clearSpanContext();
7087
DDPROF.clearContextValue(SPAN_NAME_INDEX);
7188
DDPROF.clearContextValue(RESOURCE_NAME_INDEX);
7289
}
7390

74-
@Override
75-
public void setContext(long rootSpanId, long spanId) {
76-
DDPROF.setSpanContext(spanId, rootSpanId);
77-
}
78-
7991
@Override
8092
public ProfilingContextAttribute createContextAttribute(String attribute) {
8193
return new DatadogProfilerContextSetter(attribute, DDPROF);

dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/TestProfilingContextIntegration.groovy

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,6 @@ class TestProfilingContextIntegration implements ProfilingContextIntegration {
2020
detachments.incrementAndGet()
2121
}
2222

23-
@Override
24-
void setContext(ProfilerContext profilerContext) {
25-
}
26-
27-
@Override
28-
void clearContext() {
29-
}
30-
31-
@Override
32-
void setContext(long rootSpanId, long spanId) {
33-
}
34-
3523
@Override
3624
String name() {
3725
return "test"

dd-trace-api/src/main/java/datadog/trace/api/profiling/Profiling.java

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ static Profiling get() {
2020
*
2121
* @return a profiling scope which can be closed to restore the current state.
2222
*/
23-
ProfilingScope newScope();
23+
default ProfilingScope newScope() {
24+
return ProfilingScope.NO_OP;
25+
}
2426

2527
/**
2628
* Creates a decorator for the attribute, which can be used to set and clear contexts slightly
@@ -29,20 +31,11 @@ static Profiling get() {
2931
* @param attribute the name of the attribute
3032
* @return a setter which can be used to set and clear profiling context
3133
*/
32-
ProfilingContextAttribute createContextAttribute(String attribute);
34+
default ProfilingContextAttribute createContextAttribute(String attribute) {
35+
return ProfilingContextAttribute.NoOp.INSTANCE;
36+
}
3337

3438
final class NoOp implements Profiling {
35-
3639
public static final NoOp INSTANCE = new NoOp();
37-
38-
@Override
39-
public ProfilingContextAttribute createContextAttribute(String attribute) {
40-
return ProfilingContextAttribute.NoOp.INSTANCE;
41-
}
42-
43-
@Override
44-
public ProfilingScope newScope() {
45-
return ProfilingScope.NO_OP;
46-
}
4740
}
4841
}

dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,16 @@ public final String toString() {
158158
return super.toString() + "->" + span;
159159
}
160160

161+
public final void beforeActivated() {
162+
try {
163+
scopeState.activate(span.context());
164+
} catch (Throwable e) {
165+
ContinuableScopeManager.ratelimitedLog.warn(
166+
"ScopeState {} threw exception in beforeActivated()", scopeState.getClass(), e);
167+
}
168+
}
169+
161170
public final void afterActivated() {
162-
scopeState.activate(span.context());
163171
for (final ScopeListener listener : scopeManager.scopeListeners) {
164172
try {
165173
listener.afterScopeActivated();

dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ScopeStack.java

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package datadog.trace.core.scopemanager;
22

3-
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
4-
import datadog.trace.bootstrap.instrumentation.api.ProfilerContext;
53
import datadog.trace.bootstrap.instrumentation.api.ProfilingContextIntegration;
64
import datadog.trace.bootstrap.instrumentation.api.ScopeSource;
75
import java.util.ArrayDeque;
@@ -47,19 +45,18 @@ void cleanup() {
4745
} else if (changedTop) {
4846
top = curScope;
4947
if (curScope != null) {
48+
curScope.beforeActivated();
5049
curScope.afterActivated();
5150
}
5251
}
5352
if (top == null) {
5453
onBecomeEmpty();
55-
} else {
56-
onTopChanged(top);
5754
}
5855
}
5956

6057
/** Marks a new scope as current, pushing the previous onto the stack */
6158
void push(final ContinuableScope scope) {
62-
onTopChanged(scope);
59+
scope.beforeActivated();
6360
if (top != null) {
6461
stack.push(top);
6562
} else {
@@ -110,17 +107,6 @@ void clear() {
110107
top = null;
111108
}
112109

113-
private void onTopChanged(ContinuableScope top) {
114-
AgentSpan.Context context = top.span.context();
115-
if (context instanceof ProfilerContext) {
116-
try {
117-
profilingContextIntegration.setContext((ProfilerContext) context);
118-
} catch (Throwable e) {
119-
ContinuableScopeManager.ratelimitedLog.warn("Unexpected profiling exception", e);
120-
}
121-
}
122-
}
123-
124110
/** Notifies profiler that this thread has a context now */
125111
private void onBecomeNonEmpty() {
126112
try {
@@ -133,7 +119,6 @@ private void onBecomeNonEmpty() {
133119
/** Notifies profiler that this thread no longer has a context */
134120
private void onBecomeEmpty() {
135121
try {
136-
profilingContextIntegration.clearContext();
137122
profilingContextIntegration.onDetach();
138123
} catch (Throwable e) {
139124
ContinuableScopeManager.ratelimitedLog.warn("Unexpected profiling exception", e);

0 commit comments

Comments
 (0)