JavaVersionSpecific returns millisecond precision for currentTimeNanos()
From a Java 8 JVM perspective there are limitations to the precision of time, however looking at the implementation of JavaVersionSpecific.currentTimeNanos() for Java 8, this should return as close as possible, the nanosecond precision since epoch, however it is currently only to millisecond precision.
Steps to reproduce Create two Spans in the following order
- Create and start Span 1 - startEpochNanos is set to millisecond precision
- End Span 1 - endEpochNanos is set to nanosecond precision
- Create and start Span 2 - startEpochNanos is set to millisecond precision
- End Span 2 - endEpochNanos is set to nanosecond precision
It looks like a new AnchoredClock is created for each Span if it is not inheriting from a parentSpan, therefore if the spans are created in less than 1 millisecond of each other, there is a potential the Span1.endEpochNanos is greater than Span2.startEpochNanos
What did you expect to see? I would expect Span.startEpochNanos to be at nanosecond precision
What did you see instead? Span.startEpochNanos is at millisecond precision
What version and what artifacts are you using? Artifacts: opentelemetry-sdk-common Version: 1.35
Environment OS: Centos Runtime: Java 8 OpenJdk
@scottsue I'm not aware of any reliable way of getting nanosecond precision wall time on Java 8. Do you know of something?
@breedx-splk correct, unfortunately not a reliable way. However AnchoredClock does look to attempt to get a close approximation of this. So my thoughts was to perform something similar when calculating Span.startEpochNanos
@breedx-splk correct, unfortunately not a reliable way. However
AnchoredClockdoes look to attempt to get a close approximation of this. So my thoughts was to perform something similar when calculating Span.startEpochNanos
Would the idea then be to anchor to some arbitrary previous time then?
I was just playing around to see how this could work and I created my own version of JavaVersionSpecific. The implementation requiring the following
private static final NanosecondClock SYSTEM_EPOCH_NANO_CLOCK = new NanosecondClock(null);
public long currentTimeNanos() {
return SYSTEM_EPOCH_NANO_CLOCK.getNowSinceEpochInNano();
}
This utilises a static NanoClock which gives the ability to return the nanos since epoch. In essence, this is what AnchoredClock does as well, only that it seems AnchoredClock looks to be recreated if it is not inheriting from a parentSpan? I would say it is possibly feasible to have a static instance of AnchoredClock in my above implementation to give the same functionality?
This utilises a static NanoClock which gives the ability to return the nanos since epoch.
Yeah, but you haven't shared the implementation of that class. Where is that from?
The implementation of the NanosecondClock is something that I had to hand quickly internally. However after using this, I suspect that creating a static AnchoredClock could work.
One way to get better than millisecond time on jdk8 would be to use jnr-ffi to call gettimeofday https://github.com/jnr/jnr-ffi-examples/blob/master/gettimeofday/src/main/java/gettimeofday/Gettimeofday.java We could add a SPI and bundle the jnr-ffi based time provider as separate jar so users who need it could enable it by including that jar in their project.