Skip to content

Commit cbe182d

Browse files
committed
fix(profiler): compute epoch offset dynamically in onTaskDeactivation to avoid clock drift
1 parent 18c3e3b commit cbe182d

1 file changed

Lines changed: 5 additions & 6 deletions

File tree

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,6 @@ public void onSpanFinished(AgentSpan span) {
119119
ctx.getEncodedResourceName());
120120
}
121121

122-
// Calibration offset so System.nanoTime() values can be expressed as epoch nanoseconds.
123-
// Computed once at class load to keep activation/deactivation overhead minimal.
124-
private static final long EPOCH_NANOS_OFFSET =
125-
System.currentTimeMillis() * 1_000_000L - System.nanoTime();
126-
127122
@Override
128123
public void onTaskActivation(ProfilerContext profilerContext, long startTicks) {
129124
// startTicks captured by TPEHelper is the authoritative start; nothing to do here.
@@ -140,7 +135,11 @@ public void onTaskDeactivation(ProfilerContext profilerContext, long startTicks)
140135
if (durationNanos <= 0) {
141136
return;
142137
}
143-
long startNanos = startNano + EPOCH_NANOS_OFFSET;
138+
// Compute epoch offset fresh each time: avoids cumulative drift between System.nanoTime()
139+
// (monotonic, ignores NTP/wall-clock adjustments) and System.currentTimeMillis() over the
140+
// JVM lifetime. Residual error is bounded by the 1 ms resolution of currentTimeMillis().
141+
long epochOffset = System.currentTimeMillis() * 1_000_000L - endNano;
142+
long startNanos = startNano + epochOffset;
144143
long syntheticSpanId =
145144
profilerContext.getSpanId() ^ ((long) Thread.currentThread().getId() << 32) ^ startNano;
146145
DDPROF.recordSpanNodeEvent(

0 commit comments

Comments
 (0)