Skip to content

Commit 7476064

Browse files
delay queue time rate limiting until event is committed (#7867)
* delay queue time rate limiting until event is committed * use correct native image check
1 parent 6bf7492 commit 7476064

File tree

7 files changed

+54
-28
lines changed

7 files changed

+54
-28
lines changed

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/QueueTimerHelper.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import datadog.trace.api.config.ProfilingConfig;
55
import datadog.trace.api.profiling.QueueTiming;
66
import datadog.trace.api.profiling.Timer;
7+
import datadog.trace.api.profiling.Timing;
78
import datadog.trace.api.sampling.PerRecordingRateLimiter;
89
import datadog.trace.bootstrap.ContextStore;
910
import datadog.trace.bootstrap.config.provider.ConfigProvider;
@@ -35,21 +36,28 @@ public static <T> void startQueuingTimer(
3536
}
3637

3738
public static void startQueuingTimer(State state, Class<?> schedulerClass, Object task) {
38-
if (Platform.isNativeImageBuilder()) {
39+
if (Platform.isNativeImage()) {
3940
// explicitly not supported for Graal native image
4041
return;
4142
}
4243
// avoid calling this before JFR is initialised because it will lead to reading the wrong
4344
// TSC frequency before JFR has set it up properly
44-
if (task != null
45-
&& state != null
46-
&& InstrumentationBasedProfiling.isJFRReady()
47-
&& RateLimiterHolder.RATE_LIMITER.permit()) {
45+
if (task != null && state != null && InstrumentationBasedProfiling.isJFRReady()) {
4846
QueueTiming timing =
4947
(QueueTiming) AgentTracer.get().getProfilingContext().start(Timer.TimerType.QUEUEING);
5048
timing.setTask(task);
5149
timing.setScheduler(schedulerClass);
5250
state.setTiming(timing);
5351
}
5452
}
53+
54+
public static void stopQueuingTimer(Timing timing) {
55+
if (Platform.isNativeImage()) {
56+
// explicitly not supported for Graal native image
57+
return;
58+
}
59+
if (timing != null && timing.sample() && RateLimiterHolder.RATE_LIMITER.permit()) {
60+
timing.report();
61+
}
62+
}
5563
}

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/java/concurrent/State.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public boolean isTimed() {
8585
public void stopTiming() {
8686
Timing timing = TIMING.getAndSet(this, null);
8787
if (timing != null) {
88-
timing.close();
88+
QueueTimerHelper.stopQueuingTimer(timing);
8989
}
9090
}
9191
}

dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/events/QueueTimeEvent.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,12 @@ public void setScheduler(Class<?> scheduler) {
5656
}
5757

5858
@Override
59-
public void close() {
60-
end();
61-
if (shouldCommit()) {
62-
commit();
63-
}
59+
public void report() {
60+
commit();
61+
}
62+
63+
@Override
64+
public boolean sample() {
65+
return shouldCommit();
6466
}
6567
}

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -402,17 +402,18 @@ public QueueTimeTracker newQueueTimeTracker() {
402402
return new QueueTimeTracker(this, profiler.getCurrentTicks());
403403
}
404404

405-
void recordQueueTimeEvent(
406-
long startMillis, long startTicks, Object task, Class<?> scheduler, Thread origin) {
405+
boolean shouldRecordQueueTimeEvent(long startMillis) {
406+
return System.currentTimeMillis() - startMillis >= queueTimeThresholdMillis;
407+
}
408+
409+
void recordQueueTimeEvent(long startTicks, Object task, Class<?> scheduler, Thread origin) {
407410
if (profiler != null) {
408-
if (System.currentTimeMillis() - startMillis >= queueTimeThresholdMillis) {
409-
// note: because this type traversal can update secondary_super_cache (see JDK-8180450)
410-
// we avoid doing this unless we are absolutely certain we will record the event
411-
Class<?> taskType = TaskWrapper.getUnwrappedType(task);
412-
if (taskType != null) {
413-
long endTicks = profiler.getCurrentTicks();
414-
profiler.recordQueueTime(startTicks, endTicks, taskType, scheduler, origin);
415-
}
411+
// note: because this type traversal can update secondary_super_cache (see JDK-8180450)
412+
// we avoid doing this unless we are absolutely certain we will record the event
413+
Class<?> taskType = TaskWrapper.getUnwrappedType(task);
414+
if (taskType != null) {
415+
long endTicks = profiler.getCurrentTicks();
416+
profiler.recordQueueTime(startTicks, endTicks, taskType, scheduler, origin);
416417
}
417418
}
418419
}

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,17 @@ public void setScheduler(Class<?> scheduler) {
3232
}
3333

3434
@Override
35-
public void close() {
35+
public void report() {
3636
assert weakTask != null && scheduler != null;
3737
Object task = this.weakTask.get();
3838
if (task != null) {
3939
// indirection reduces shallow size of the tracker instance
40-
profiler.recordQueueTimeEvent(startMillis, startTicks, task, scheduler, origin);
40+
profiler.recordQueueTimeEvent(startTicks, task, scheduler, origin);
4141
}
4242
}
43+
44+
@Override
45+
public boolean sample() {
46+
return profiler.shouldRecordQueueTimeEvent(startMillis);
47+
}
4348
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class TestProfilingContextIntegration implements ProfilingContextIntegration {
9999
}
100100

101101
@Override
102-
void close() {
102+
void report() {
103103
counter.decrementAndGet()
104104
AgentSpan span = AgentTracer.activeSpan()
105105
long activeSpanId = span == null ? 0 : span.getSpanId()
@@ -109,6 +109,10 @@ class TestProfilingContextIntegration implements ProfilingContextIntegration {
109109
closedTimings.offer(this)
110110
}
111111

112+
@Override
113+
boolean sample() {
114+
return true
115+
}
112116

113117
@Override
114118
String toString() {

internal-api/src/main/java/datadog/trace/api/profiling/Timing.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
package datadog.trace.api.profiling;
22

3-
public interface Timing extends AutoCloseable {
4-
@Override
5-
void close();
3+
public interface Timing {
4+
void report();
5+
6+
boolean sample();
67

78
class NoOp implements Timing, QueueTiming {
89
public static final Timing INSTANCE = new NoOp();
910

1011
@Override
11-
public void close() {}
12+
public void report() {}
13+
14+
@Override
15+
public boolean sample() {
16+
return false;
17+
}
1218

1319
@Override
1420
public void setTask(Object task) {}

0 commit comments

Comments
 (0)