Change clock and converter to use epoch nanos (#636)

Signed-off-by: Bogdan Drutu <bogdandrutu@gmail.com>
This commit is contained in:
Bogdan Drutu 2019-10-25 13:35:11 -07:00 committed by GitHub
parent ab00d64b4c
commit bd14f39727
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 110 additions and 149 deletions

View File

@ -35,7 +35,8 @@ public abstract class Timestamp {
private static final long MAX_SECONDS = 315576000000L; private static final long MAX_SECONDS = 315576000000L;
private static final int MAX_NANOS = 999999999; private static final int MAX_NANOS = 999999999;
private static final long MILLIS_PER_SECOND = 1000L; private static final long MILLIS_PER_SECOND = 1000L;
private static final long NANOS_PER_MILLI = 1000 * 1000; private static final long NANOS_PER_SECOND = 1000L * 1000L * 1000L;
private static final long NANOS_PER_MILLI = 1000L * 1000L;
Timestamp() {} Timestamp() {}
@ -85,6 +86,21 @@ public abstract class Timestamp {
return create(secs, (int) (mos * NANOS_PER_MILLI)); // Safe int * NANOS_PER_MILLI return create(secs, (int) (mos * NANOS_PER_MILLI)); // Safe int * NANOS_PER_MILLI
} }
/**
* Creates a new timestamp from the given milliseconds.
*
* @param epochNanos the timestamp represented in nanoseconds since epoch.
* @return new {@code Timestamp} with specified fields.
* @throws IllegalArgumentException if the number of milliseconds is out of the range that can be
* represented by {@code Timestamp}.
* @since 0.1.0
*/
public static Timestamp fromNanos(long epochNanos) {
long secs = floorDiv(epochNanos, NANOS_PER_SECOND);
int nanos = (int) floorMod(epochNanos, NANOS_PER_SECOND);
return create(secs, nanos); // Safe int * NANOS_PER_MILLI
}
/** /**
* Returns the number of seconds since the Unix Epoch represented by this timestamp. * Returns the number of seconds since the Unix Epoch represented by this timestamp.
* *

View File

@ -16,8 +16,6 @@
package io.opentelemetry.sdk.internal; package io.opentelemetry.sdk.internal;
import io.opentelemetry.sdk.common.Timestamp;
/** /**
* Interface for getting the current time. * Interface for getting the current time.
* *
@ -25,12 +23,12 @@ import io.opentelemetry.sdk.common.Timestamp;
*/ */
public interface Clock { public interface Clock {
/** /**
* Obtains the current instant from this clock. * Obtains the current epoch timestamp in nanos from this clock.
* *
* @return the current instant. * @return the current epoch timestamp in nanos.
* @since 0.1.0 * @since 0.1.0
*/ */
Timestamp now(); long now();
/** /**
* Returns a time measurement with nanosecond precision that can only be used to calculate elapsed * Returns a time measurement with nanosecond precision that can only be used to calculate elapsed
@ -40,5 +38,5 @@ public interface Clock {
* time. * time.
* @since 0.1.0 * @since 0.1.0
*/ */
long nowNanos(); long nanoTime();
} }

View File

@ -16,7 +16,7 @@
package io.opentelemetry.sdk.internal; package io.opentelemetry.sdk.internal;
import io.opentelemetry.sdk.common.Timestamp; import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
/** A {@link Clock} that uses {@link System#currentTimeMillis()} and {@link System#nanoTime()}. */ /** A {@link Clock} that uses {@link System#currentTimeMillis()} and {@link System#nanoTime()}. */
@ -37,12 +37,12 @@ public final class MillisClock implements Clock {
} }
@Override @Override
public Timestamp now() { public long now() {
return Timestamp.fromMillis(System.currentTimeMillis()); return TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis());
} }
@Override @Override
public long nowNanos() { public long nanoTime() {
return System.nanoTime(); return System.nanoTime();
} }
} }

View File

@ -17,9 +17,8 @@
package io.opentelemetry.sdk.internal; package io.opentelemetry.sdk.internal;
import static io.opentelemetry.sdk.internal.TimestampConverter.NANOS_PER_MILLI; import static io.opentelemetry.sdk.internal.TimestampConverter.NANOS_PER_MILLI;
import static io.opentelemetry.sdk.internal.TimestampConverter.NANOS_PER_SECOND;
import io.opentelemetry.sdk.common.Timestamp; import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
@ -32,10 +31,10 @@ import javax.annotation.concurrent.ThreadSafe;
public class TestClock implements Clock { public class TestClock implements Clock {
@GuardedBy("this") @GuardedBy("this")
private Timestamp currentTimestamp; private long currentEpochNanos;
private TestClock(Timestamp timestamp) { private TestClock(long epochNanos) {
currentTimestamp = timestamp; currentEpochNanos = epochNanos;
} }
/** /**
@ -46,28 +45,28 @@ public class TestClock implements Clock {
*/ */
public static TestClock create() { public static TestClock create() {
// Set Time to Tuesday, May 7, 2019 12:00:00 AM GMT-07:00 DST // Set Time to Tuesday, May 7, 2019 12:00:00 AM GMT-07:00 DST
return create(Timestamp.fromMillis(1_557_212_400_000L)); return create(TimeUnit.MILLISECONDS.toNanos(1_557_212_400_000L));
} }
/** /**
* Creates a clock with the given time. * Creates a clock with the given time.
* *
* @param timestamp the initial time. * @param epochNanos the initial time in nanos since epoch.
* @return a new {@code TestClock} with the given time. * @return a new {@code TestClock} with the given time.
* @since 0.1.0 * @since 0.1.0
*/ */
public static TestClock create(Timestamp timestamp) { public static TestClock create(long epochNanos) {
return new TestClock(timestamp); return new TestClock(epochNanos);
} }
/** /**
* Sets the time. * Sets the time.
* *
* @param timestamp the new time. * @param epochNanos the new time.
* @since 0.1.0 * @since 0.1.0
*/ */
public synchronized void setTime(Timestamp timestamp) { public synchronized void setTime(long epochNanos) {
currentTimestamp = timestamp; currentEpochNanos = epochNanos;
} }
/** /**
@ -77,27 +76,17 @@ public class TestClock implements Clock {
* @since 0.1.0 * @since 0.1.0
*/ */
public synchronized void advanceMillis(long millis) { public synchronized void advanceMillis(long millis) {
long incomingSeconds = millis / 1000; long nanos = millis * NANOS_PER_MILLI;
long remainingMillis = millis % 1000; currentEpochNanos += nanos;
long remainingNanos = remainingMillis * NANOS_PER_MILLI;
long newSeconds = incomingSeconds + currentTimestamp.getSeconds();
long newNanos = remainingNanos + currentTimestamp.getNanos();
if (newNanos >= NANOS_PER_SECOND) {
newSeconds += newNanos / NANOS_PER_SECOND;
newNanos = newNanos % NANOS_PER_SECOND;
}
currentTimestamp = Timestamp.create(newSeconds, (int) newNanos);
} }
@Override @Override
public synchronized Timestamp now() { public synchronized long now() {
return currentTimestamp; return currentEpochNanos;
} }
@Override @Override
public synchronized long nowNanos() { public synchronized long nanoTime() {
return (currentTimestamp.getSeconds() * NANOS_PER_SECOND) + currentTimestamp.getNanos(); return currentEpochNanos;
} }
} }

View File

@ -29,7 +29,7 @@ public class TimestampConverter {
static final long NANOS_PER_SECOND = 1_000_000_000; static final long NANOS_PER_SECOND = 1_000_000_000;
static final long NANOS_PER_MILLI = 1_000_000; static final long NANOS_PER_MILLI = 1_000_000;
private final Timestamp timestamp; private final long epochNanos;
private final long nanoTime; private final long nanoTime;
/** /**
@ -39,7 +39,7 @@ public class TimestampConverter {
* @return a {@code TimestampConverter} initialized to now. * @return a {@code TimestampConverter} initialized to now.
*/ */
public static TimestampConverter now(Clock clock) { public static TimestampConverter now(Clock clock) {
return new TimestampConverter(clock.now(), clock.nowNanos()); return new TimestampConverter(clock.now(), clock.nanoTime());
} }
/** /**
@ -48,21 +48,13 @@ public class TimestampConverter {
* @param nanoTime value to convert. * @param nanoTime value to convert.
* @return the {@code Timestamp} representation of the {@code time}. * @return the {@code Timestamp} representation of the {@code time}.
*/ */
public Timestamp convertNanoTime(long nanoTime) { public long convertNanoTime(long nanoTime) {
long deltaNanos = nanoTime - this.nanoTime; long deltaNanos = nanoTime - this.nanoTime;
return epochNanos + deltaNanos;
long seconds = timestamp.getSeconds() + (deltaNanos / NANOS_PER_SECOND);
long nanos = timestamp.getNanos() + (deltaNanos % NANOS_PER_SECOND);
if (nanos >= NANOS_PER_SECOND) {
seconds += nanos / NANOS_PER_SECOND;
nanos = nanos % NANOS_PER_SECOND;
}
return Timestamp.create(seconds, (int) nanos);
} }
private TimestampConverter(Timestamp timestamp, long nanoTime) { private TimestampConverter(long epochNanos, long nanoTime) {
this.timestamp = timestamp; this.epochNanos = epochNanos;
this.nanoTime = nanoTime; this.nanoTime = nanoTime;
} }
} }

View File

@ -156,8 +156,10 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
@Override @Override
public SpanData toSpanData() { public SpanData toSpanData() {
Timestamp startTimestamp = timestampConverter.convertNanoTime(startNanoTime); Timestamp startTimestamp =
Timestamp endTimestamp = timestampConverter.convertNanoTime(getEndNanoTime()); Timestamp.fromNanos(timestampConverter.convertNanoTime(startNanoTime));
Timestamp endTimestamp =
Timestamp.fromNanos(timestampConverter.convertNanoTime(getEndNanoTime()));
SpanContext spanContext = getSpanContext(); SpanContext spanContext = getSpanContext();
return SpanData.newBuilder() return SpanData.newBuilder()
.setName(getName()) .setName(getName())
@ -188,7 +190,8 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
private static SpanData.TimedEvent adaptTimedEvent( private static SpanData.TimedEvent adaptTimedEvent(
io.opentelemetry.sdk.trace.TimedEvent sourceEvent, TimestampConverter timestampConverter) { io.opentelemetry.sdk.trace.TimedEvent sourceEvent, TimestampConverter timestampConverter) {
Timestamp timestamp = timestampConverter.convertNanoTime(sourceEvent.getNanotime()); Timestamp timestamp =
Timestamp.fromNanos(timestampConverter.convertNanoTime(sourceEvent.getNanotime()));
return SpanData.TimedEvent.create( return SpanData.TimedEvent.create(
timestamp, sourceEvent.getName(), sourceEvent.getAttributes()); timestamp, sourceEvent.getName(), sourceEvent.getAttributes());
} }
@ -212,7 +215,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
/** /**
* Returns the end nano time (see {@link System#nanoTime()}). If the current {@code Span} is not * Returns the end nano time (see {@link System#nanoTime()}). If the current {@code Span} is not
* ended then returns {@link Clock#nowNanos()}. * ended then returns {@link Clock#nanoTime()}.
* *
* @return the end nano time. * @return the end nano time.
*/ */
@ -297,7 +300,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
// Use getEndNanoTimeInternal to avoid over-locking. // Use getEndNanoTimeInternal to avoid over-locking.
@GuardedBy("this") @GuardedBy("this")
private long getEndNanoTimeInternal() { private long getEndNanoTimeInternal() {
return hasBeenEnded ? endNanoTime : clock.nowNanos(); return hasBeenEnded ? endNanoTime : clock.nanoTime();
} }
/** /**
@ -365,35 +368,35 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
@Override @Override
public void addEvent(String name) { public void addEvent(String name) {
addTimedEvent(TimedEvent.create(clock.nowNanos(), name)); addTimedEvent(TimedEvent.create(clock.nanoTime(), name));
} }
// TODO: Use timestamp. // TODO: Use timestamp.
@Override @Override
public void addEvent(String name, long timestamp) { public void addEvent(String name, long timestamp) {
addTimedEvent(TimedEvent.create(clock.nowNanos(), name)); addTimedEvent(TimedEvent.create(clock.nanoTime(), name));
} }
@Override @Override
public void addEvent(String name, Map<String, AttributeValue> attributes) { public void addEvent(String name, Map<String, AttributeValue> attributes) {
addTimedEvent(TimedEvent.create(clock.nowNanos(), name, attributes)); addTimedEvent(TimedEvent.create(clock.nanoTime(), name, attributes));
} }
// TODO: Use timestamp. // TODO: Use timestamp.
@Override @Override
public void addEvent(String name, Map<String, AttributeValue> attributes, long timestamp) { public void addEvent(String name, Map<String, AttributeValue> attributes, long timestamp) {
addTimedEvent(TimedEvent.create(clock.nowNanos(), name, attributes)); addTimedEvent(TimedEvent.create(clock.nanoTime(), name, attributes));
} }
@Override @Override
public void addEvent(Event event) { public void addEvent(Event event) {
addTimedEvent(TimedEvent.create(clock.nowNanos(), event)); addTimedEvent(TimedEvent.create(clock.nanoTime(), event));
} }
// TODO: Use timestamp. // TODO: Use timestamp.
@Override @Override
public void addEvent(Event event, long timestamp) { public void addEvent(Event event, long timestamp) {
addTimedEvent(TimedEvent.create(clock.nowNanos(), event)); addTimedEvent(TimedEvent.create(clock.nanoTime(), event));
} }
private void addTimedEvent(TimedEvent timedEvent) { private void addTimedEvent(TimedEvent timedEvent) {
@ -438,7 +441,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
logger.log(Level.FINE, "Calling end() on an ended Span."); logger.log(Level.FINE, "Calling end() on an ended Span.");
return; return;
} }
endNanoTime = clock.nowNanos(); endNanoTime = clock.nanoTime();
hasBeenEnded = true; hasBeenEnded = true;
} }
spanProcessor.onEnd(this); spanProcessor.onEnd(this);
@ -555,7 +558,7 @@ final class RecordEventsReadableSpan implements ReadableSpan, Span {
this.numberOfChildren = 0; this.numberOfChildren = 0;
this.timestampConverter = this.timestampConverter =
timestampConverter != null ? timestampConverter : TimestampConverter.now(clock); timestampConverter != null ? timestampConverter : TimestampConverter.now(clock);
startNanoTime = clock.nowNanos(); startNanoTime = clock.nanoTime();
if (!attributes.isEmpty()) { if (!attributes.isEmpty()) {
getInitializedAttributes().putAll(attributes); getInitializedAttributes().putAll(attributes);
} }

View File

@ -1,30 +0,0 @@
/*
* Copyright 2019, OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.opentelemetry.sdk.internal;
import io.opentelemetry.sdk.common.Timestamp;
final class ClockTestUtil {
static final int NANOS_PER_SECOND = 1000 * 1000 * 1000;
static final int NANOS_PER_MILLI = 1000 * 1000;
static Timestamp createTimestamp(long seconds, int nanos) {
return Timestamp.create(seconds, nanos);
}
private ClockTestUtil() {}
}

View File

@ -28,27 +28,25 @@ public final class TestClockTest {
@Test @Test
public void setAndGetTime() { public void setAndGetTime() {
TestClock clock = TestClock.create(ClockTestUtil.createTimestamp(1, 2)); TestClock clock = TestClock.create(1234);
assertThat(clock.now()).isEqualTo(ClockTestUtil.createTimestamp(1, 2)); assertThat(clock.now()).isEqualTo(1234);
clock.setTime(ClockTestUtil.createTimestamp(3, 4)); clock.setTime(9876543210L);
assertThat(clock.now()).isEqualTo(ClockTestUtil.createTimestamp(3, 4)); assertThat(clock.now()).isEqualTo(9876543210L);
} }
@Test @Test
public void advanceMillis() { public void advanceMillis() {
TestClock clock = TestClock clock = TestClock.create(1_500_000_000L);
TestClock.create(ClockTestUtil.createTimestamp(1, 500 * ClockTestUtil.NANOS_PER_MILLI));
clock.advanceMillis(2600); clock.advanceMillis(2600);
assertThat(clock.now()) assertThat(clock.now()).isEqualTo(4_100_000_000L);
.isEqualTo(ClockTestUtil.createTimestamp(4, 100 * ClockTestUtil.NANOS_PER_MILLI));
} }
@Test @Test
public void measureElapsedTime() { public void measureElapsedTime() {
TestClock clock = TestClock.create(ClockTestUtil.createTimestamp(10, 1)); TestClock clock = TestClock.create(10_000_000_001L);
long nanos1 = clock.nowNanos(); long nanos1 = clock.nanoTime();
clock.setTime(ClockTestUtil.createTimestamp(11, 5)); clock.setTime(11_000_000_005L);
long nanos2 = clock.nowNanos(); long nanos2 = clock.nanoTime();
assertThat(nanos2 - nanos1).isEqualTo(ClockTestUtil.NANOS_PER_SECOND + 4); assertThat(nanos2 - nanos1).isEqualTo(1_000_000_004L);
} }
} }

View File

@ -17,9 +17,7 @@
package io.opentelemetry.sdk.internal; package io.opentelemetry.sdk.internal;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static io.opentelemetry.sdk.internal.ClockTestUtil.createTimestamp;
import io.opentelemetry.sdk.common.Timestamp;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.JUnit4; import org.junit.runners.JUnit4;
@ -27,35 +25,35 @@ import org.junit.runners.JUnit4;
/** Unit tests for {@link TimestampConverter}. */ /** Unit tests for {@link TimestampConverter}. */
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public class TimestampConverterTest { public class TimestampConverterTest {
private final Timestamp timestamp = createTimestamp(1234, 5678); private final long epochNanos = 1234_000_005_678L;
private final TestClock testClock = TestClock.create(timestamp); private final TestClock testClock = TestClock.create(epochNanos);
@Test @Test
public void now() { public void now() {
assertThat(testClock.now()).isEqualTo(timestamp); assertThat(testClock.now()).isEqualTo(epochNanos);
TimestampConverter timeConverter = TimestampConverter.now(testClock); TimestampConverter timeConverter = TimestampConverter.now(testClock);
assertThat(timeConverter.convertNanoTime(testClock.nowNanos())).isEqualTo(timestamp); assertThat(timeConverter.convertNanoTime(testClock.nanoTime())).isEqualTo(epochNanos);
} }
@Test @Test
public void convertNanoTime_Positive() { public void convertNanoTime_Positive() {
TimestampConverter timeConverter = TimestampConverter.now(testClock); TimestampConverter timeConverter = TimestampConverter.now(testClock);
assertThat(timeConverter.convertNanoTime(testClock.nowNanos() + 3210)) assertThat(timeConverter.convertNanoTime(testClock.nanoTime() + 3210))
.isEqualTo(createTimestamp(1234, 8888)); .isEqualTo(1234_000_008_888L);
assertThat(timeConverter.convertNanoTime(testClock.nowNanos() + 1000)) assertThat(timeConverter.convertNanoTime(testClock.nanoTime() + 1000))
.isEqualTo(createTimestamp(1234, 6678)); .isEqualTo(1234_000_006_678L);
assertThat(timeConverter.convertNanoTime(testClock.nowNanos() + 15_999_994_322L)) assertThat(timeConverter.convertNanoTime(testClock.nanoTime() + 15_999_994_322L))
.isEqualTo(createTimestamp(1250, 0)); .isEqualTo(1250_000_000_000L);
} }
@Test @Test
public void convertNanoTime_Negative() { public void convertNanoTime_Negative() {
TimestampConverter timeConverter = TimestampConverter.now(testClock); TimestampConverter timeConverter = TimestampConverter.now(testClock);
assertThat(timeConverter.convertNanoTime(testClock.nowNanos() - 3456)) assertThat(timeConverter.convertNanoTime(testClock.nanoTime() - 3456))
.isEqualTo(createTimestamp(1234, 2222)); .isEqualTo(1234_000_002_222L);
assertThat(timeConverter.convertNanoTime(testClock.nowNanos() - 1000)) assertThat(timeConverter.convertNanoTime(testClock.nanoTime() - 1000))
.isEqualTo(createTimestamp(1234, 4678)); .isEqualTo(1234_000_004_678L);
assertThat(timeConverter.convertNanoTime(testClock.nowNanos() - 14000005678L)) assertThat(timeConverter.convertNanoTime(testClock.nanoTime() - 14000005678L))
.isEqualTo(createTimestamp(1220, 0)); .isEqualTo(1220_000_000_000L);
} }
} }

View File

@ -64,8 +64,8 @@ public class RecordEventsReadableSpanTest {
private final SpanId parentSpanId = TestUtils.generateRandomSpanId(); private final SpanId parentSpanId = TestUtils.generateRandomSpanId();
private final SpanContext spanContext = private final SpanContext spanContext =
SpanContext.create(traceId, spanId, TraceFlags.getDefault(), Tracestate.getDefault()); SpanContext.create(traceId, spanId, TraceFlags.getDefault(), Tracestate.getDefault());
private final Timestamp startTime = Timestamp.create(1000, 0); private final long startEpochNanos = 1000_123_789_654L;
private final TestClock testClock = TestClock.create(startTime); private final TestClock testClock = TestClock.create(startEpochNanos);
private final TimestampConverter timestampConverter = TimestampConverter.now(testClock); private final TimestampConverter timestampConverter = TimestampConverter.now(testClock);
private final Resource resource = Resource.getEmpty(); private final Resource resource = Resource.getEmpty();
private final Map<String, AttributeValue> attributes = new HashMap<>(); private final Map<String, AttributeValue> attributes = new HashMap<>();
@ -101,8 +101,8 @@ public class RecordEventsReadableSpanTest {
Collections.<SpanData.TimedEvent>emptyList(), Collections.<SpanData.TimedEvent>emptyList(),
Collections.singletonList(link), Collections.singletonList(link),
SPAN_NAME, SPAN_NAME,
Timestamp.create(startTime.getSeconds(), 0), Timestamp.fromNanos(startEpochNanos),
Timestamp.create(startTime.getSeconds(), 0), Timestamp.fromNanos(startEpochNanos),
Status.OK); Status.OK);
} }
@ -121,7 +121,7 @@ public class RecordEventsReadableSpanTest {
SpanData spanData = span.toSpanData(); SpanData spanData = span.toSpanData();
SpanData.TimedEvent timedEvent = SpanData.TimedEvent timedEvent =
SpanData.TimedEvent.create( SpanData.TimedEvent.create(
Timestamp.create(startTime.getSeconds() + 1, 0), Timestamp.fromNanos(startEpochNanos + NANOS_PER_SECOND),
"event2", "event2",
Collections.<String, AttributeValue>emptyMap()); Collections.<String, AttributeValue>emptyMap());
verifySpanData( verifySpanData(
@ -130,8 +130,8 @@ public class RecordEventsReadableSpanTest {
Collections.singletonList(timedEvent), Collections.singletonList(timedEvent),
Collections.singletonList(link), Collections.singletonList(link),
SPAN_NEW_NAME, SPAN_NEW_NAME,
Timestamp.create(startTime.getSeconds(), 0), Timestamp.fromNanos(startEpochNanos),
Timestamp.create(testClock.now().getSeconds(), 0), Timestamp.fromNanos(testClock.now()),
Status.OK); Status.OK);
} finally { } finally {
span.end(); span.end();
@ -150,7 +150,7 @@ public class RecordEventsReadableSpanTest {
SpanData spanData = span.toSpanData(); SpanData spanData = span.toSpanData();
SpanData.TimedEvent timedEvent = SpanData.TimedEvent timedEvent =
SpanData.TimedEvent.create( SpanData.TimedEvent.create(
Timestamp.create(startTime.getSeconds() + 1, 0), Timestamp.fromNanos(startEpochNanos + NANOS_PER_SECOND),
"event2", "event2",
Collections.<String, AttributeValue>emptyMap()); Collections.<String, AttributeValue>emptyMap());
verifySpanData( verifySpanData(
@ -159,8 +159,8 @@ public class RecordEventsReadableSpanTest {
Collections.singletonList(timedEvent), Collections.singletonList(timedEvent),
Collections.singletonList(link), Collections.singletonList(link),
SPAN_NEW_NAME, SPAN_NEW_NAME,
Timestamp.create(startTime.getSeconds(), 0), Timestamp.fromNanos(startEpochNanos),
Timestamp.create(testClock.now().getSeconds(), 0), Timestamp.fromNanos(testClock.now()),
Status.CANCELLED); Status.CANCELLED);
} }
@ -225,12 +225,10 @@ public class RecordEventsReadableSpanTest {
RecordEventsReadableSpan span = createTestSpan(Kind.INTERNAL); RecordEventsReadableSpan span = createTestSpan(Kind.INTERNAL);
try { try {
testClock.advanceMillis(MILLIS_PER_SECOND); testClock.advanceMillis(MILLIS_PER_SECOND);
long elapsedTimeNanos1 = long elapsedTimeNanos1 = testClock.now() - startEpochNanos;
(testClock.now().getSeconds() - startTime.getSeconds()) * NANOS_PER_SECOND;
assertThat(span.getLatencyNs()).isEqualTo(elapsedTimeNanos1); assertThat(span.getLatencyNs()).isEqualTo(elapsedTimeNanos1);
testClock.advanceMillis(MILLIS_PER_SECOND); testClock.advanceMillis(MILLIS_PER_SECOND);
long elapsedTimeNanos2 = long elapsedTimeNanos2 = testClock.now() - startEpochNanos;
(testClock.now().getSeconds() - startTime.getSeconds()) * NANOS_PER_SECOND;
assertThat(span.getLatencyNs()).isEqualTo(elapsedTimeNanos2); assertThat(span.getLatencyNs()).isEqualTo(elapsedTimeNanos2);
} finally { } finally {
span.end(); span.end();
@ -242,8 +240,7 @@ public class RecordEventsReadableSpanTest {
RecordEventsReadableSpan span = createTestSpan(Kind.INTERNAL); RecordEventsReadableSpan span = createTestSpan(Kind.INTERNAL);
testClock.advanceMillis(MILLIS_PER_SECOND); testClock.advanceMillis(MILLIS_PER_SECOND);
span.end(); span.end();
long elapsedTimeNanos = long elapsedTimeNanos = testClock.now() - startEpochNanos;
(testClock.now().getSeconds() - startTime.getSeconds()) * NANOS_PER_SECOND;
assertThat(span.getLatencyNs()).isEqualTo(elapsedTimeNanos); assertThat(span.getLatencyNs()).isEqualTo(elapsedTimeNanos);
testClock.advanceMillis(MILLIS_PER_SECOND); testClock.advanceMillis(MILLIS_PER_SECOND);
assertThat(span.getLatencyNs()).isEqualTo(elapsedTimeNanos); assertThat(span.getLatencyNs()).isEqualTo(elapsedTimeNanos);
@ -384,7 +381,7 @@ public class RecordEventsReadableSpanTest {
for (int i = 0; i < maxNumberOfEvents; i++) { for (int i = 0; i < maxNumberOfEvents; i++) {
SpanData.TimedEvent expectedEvent = SpanData.TimedEvent expectedEvent =
SpanData.TimedEvent.create( SpanData.TimedEvent.create(
Timestamp.create(startTime.getSeconds() + maxNumberOfEvents + i, 0), Timestamp.fromNanos(startEpochNanos + (maxNumberOfEvents + i) * NANOS_PER_SECOND),
"event2", "event2",
Collections.<String, AttributeValue>emptyMap()); Collections.<String, AttributeValue>emptyMap());
assertThat(spanData.getTimedEvents().get(i)).isEqualTo(expectedEvent); assertThat(spanData.getTimedEvents().get(i)).isEqualTo(expectedEvent);
@ -397,7 +394,7 @@ public class RecordEventsReadableSpanTest {
for (int i = 0; i < maxNumberOfEvents; i++) { for (int i = 0; i < maxNumberOfEvents; i++) {
SpanData.TimedEvent expectedEvent = SpanData.TimedEvent expectedEvent =
SpanData.TimedEvent.create( SpanData.TimedEvent.create(
Timestamp.create(startTime.getSeconds() + maxNumberOfEvents + i, 0), Timestamp.fromNanos(startEpochNanos + (maxNumberOfEvents + i) * NANOS_PER_SECOND),
"event2", "event2",
Collections.<String, AttributeValue>emptyMap()); Collections.<String, AttributeValue>emptyMap());
assertThat(spanData.getTimedEvents().get(i)).isEqualTo(expectedEvent); assertThat(spanData.getTimedEvents().get(i)).isEqualTo(expectedEvent);
@ -528,17 +525,17 @@ public class RecordEventsReadableSpanTest {
attributes, attributes,
links, links,
1); 1);
long startTimeNanos = clock.nowNanos(); long startTimeNanos = clock.nanoTime();
clock.advanceMillis(4); clock.advanceMillis(4);
long firstEventTimeNanos = clock.nowNanos(); long firstEventTimeNanos = clock.nanoTime();
readableSpan.addEvent("event1", event1Attributes); readableSpan.addEvent("event1", event1Attributes);
clock.advanceMillis(6); clock.advanceMillis(6);
long secondEventTimeNanos = clock.nowNanos(); long secondEventTimeNanos = clock.nanoTime();
readableSpan.addEvent("event2", event2Attributes); readableSpan.addEvent("event2", event2Attributes);
clock.advanceMillis(100); clock.advanceMillis(100);
readableSpan.end(); readableSpan.end();
long endTimeNanos = clock.nowNanos(); long endTimeNanos = clock.nanoTime();
SpanData expected = SpanData expected =
SpanData.newBuilder() SpanData.newBuilder()