Add unit to start, end and event timestamp accepting methods in Span. (#1969)
* Add unit to timestamp accepting methods in Span. * end timestamp * Merge * Merge * Add Instant versions too
This commit is contained in:
parent
9063c385d9
commit
1883c578bd
|
|
@ -10,6 +10,7 @@ import io.opentelemetry.api.common.Attributes;
|
|||
import io.opentelemetry.api.internal.Utils;
|
||||
import io.opentelemetry.context.Context;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
|
|
@ -107,7 +108,7 @@ final class DefaultTracer implements Tracer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public NoopSpanBuilder setStartTimestamp(long startTimestamp) {
|
||||
public NoopSpanBuilder setStartTimestamp(long startTimestamp, TimeUnit unit) {
|
||||
Utils.checkArgument(startTimestamp >= 0, "Negative startTimestamp");
|
||||
return this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package io.opentelemetry.api.trace;
|
|||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
|
|
@ -71,7 +72,7 @@ final class PropagatedSpan implements Span {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Span addEvent(String name, long timestamp) {
|
||||
public Span addEvent(String name, long timestamp, TimeUnit unit) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ final class PropagatedSpan implements Span {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Span addEvent(String name, Attributes attributes, long timestamp) {
|
||||
public Span addEvent(String name, Attributes attributes, long timestamp, TimeUnit unit) {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +115,7 @@ final class PropagatedSpan implements Span {
|
|||
public void end() {}
|
||||
|
||||
@Override
|
||||
public void end(long timestamp) {}
|
||||
public void end(long timestamp, TimeUnit unit) {}
|
||||
|
||||
@Override
|
||||
public SpanContext getSpanContext() {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,15 @@
|
|||
|
||||
package io.opentelemetry.api.trace;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.ImplicitContextKeyed;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
|
@ -199,10 +204,32 @@ public interface Span extends ImplicitContextKeyed {
|
|||
* occurred.
|
||||
*
|
||||
* @param name the name of the event.
|
||||
* @param timestamp the explicit event timestamp in nanos since epoch.
|
||||
* @param timestamp the explicit event timestamp since epoch.
|
||||
* @param unit the unit of the timestamp
|
||||
* @return this.
|
||||
*/
|
||||
Span addEvent(String name, long timestamp);
|
||||
Span addEvent(String name, long timestamp, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Adds an event to the {@link Span} with the given {@code timestamp}, as nanos since epoch. Note,
|
||||
* this {@code timestamp} is not the same as {@link System#nanoTime()} but may be computed using
|
||||
* it, for example, by taking a difference of readings from {@link System#nanoTime()} and adding
|
||||
* to the span start time.
|
||||
*
|
||||
* <p>When possible, it is preferred to use {@link #addEvent(String)} at the time the event
|
||||
* occurred.
|
||||
*
|
||||
* @param name the name of the event.
|
||||
* @param timestamp the explicit event timestamp since epoch.
|
||||
* @return this.
|
||||
*/
|
||||
default Span addEvent(String name, Instant timestamp) {
|
||||
if (timestamp == null) {
|
||||
return addEvent(name);
|
||||
}
|
||||
return addEvent(
|
||||
name, SECONDS.toNanos(timestamp.getEpochSecond()) + timestamp.getNano(), NANOSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event to the {@link Span} with the given {@link Attributes}. The timestamp of the event
|
||||
|
|
@ -227,10 +254,37 @@ public interface Span extends ImplicitContextKeyed {
|
|||
* @param name the name of the event.
|
||||
* @param attributes the attributes that will be added; these are associated with this event, not
|
||||
* the {@code Span} as for {@code setAttribute()}.
|
||||
* @param timestamp the explicit event timestamp in nanos since epoch.
|
||||
* @param timestamp the explicit event timestamp since epoch.
|
||||
* @param unit the unit of the timestamp
|
||||
* @return this.
|
||||
*/
|
||||
Span addEvent(String name, Attributes attributes, long timestamp);
|
||||
Span addEvent(String name, Attributes attributes, long timestamp, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Adds an event to the {@link Span} with the given {@link Attributes} and {@code timestamp}.
|
||||
* Note, this {@code timestamp} is not the same as {@link System#nanoTime()} but may be computed
|
||||
* using it, for example, by taking a difference of readings from {@link System#nanoTime()} and
|
||||
* adding to the span start time.
|
||||
*
|
||||
* <p>When possible, it is preferred to use {@link #addEvent(String)} at the time the event
|
||||
* occurred.
|
||||
*
|
||||
* @param name the name of the event.
|
||||
* @param attributes the attributes that will be added; these are associated with this event, not
|
||||
* the {@code Span} as for {@code setAttribute()}.
|
||||
* @param timestamp the explicit event timestamp since epoch.
|
||||
* @return this.
|
||||
*/
|
||||
default Span addEvent(String name, Attributes attributes, Instant timestamp) {
|
||||
if (timestamp == null) {
|
||||
return addEvent(name, attributes);
|
||||
}
|
||||
return addEvent(
|
||||
name,
|
||||
attributes,
|
||||
SECONDS.toNanos(timestamp.getEpochSecond()) + timestamp.getNano(),
|
||||
NANOSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the status to the {@code Span}.
|
||||
|
|
@ -312,10 +366,31 @@ public interface Span extends ImplicitContextKeyed {
|
|||
* <p>Use this method for specifying explicit end options, such as end {@code Timestamp}. When no
|
||||
* explicit values are required, use {@link #end()}.
|
||||
*
|
||||
* @param timestamp the explicit timestamp, as nanos from the epoch, for this {@code Span}. {@code
|
||||
* 0} indicates current time should be used.
|
||||
* @param timestamp the explicit timestamp from the epoch, for this {@code Span}. {@code 0}
|
||||
* indicates current time should be used.
|
||||
* @param unit the unit of the timestamp
|
||||
*/
|
||||
void end(long timestamp);
|
||||
void end(long timestamp, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Marks the end of {@code Span} execution with the specified timestamp.
|
||||
*
|
||||
* <p>Only the timing of the first end call for a given {@code Span} will be recorded, and
|
||||
* implementations are free to ignore all further calls.
|
||||
*
|
||||
* <p>Use this method for specifying explicit end options, such as end {@code Timestamp}. When no
|
||||
* explicit values are required, use {@link #end()}.
|
||||
*
|
||||
* @param timestamp the explicit timestamp from the epoch, for this {@code Span}. {@code 0}
|
||||
* indicates current time should be used.
|
||||
*/
|
||||
default void end(Instant timestamp) {
|
||||
if (timestamp == null) {
|
||||
end();
|
||||
return;
|
||||
}
|
||||
end(SECONDS.toNanos(timestamp.getEpochSecond()) + timestamp.getNano(), NANOSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code SpanContext} associated with this {@code Span}.
|
||||
|
|
@ -570,11 +645,32 @@ public interface Span extends ImplicitContextKeyed {
|
|||
*
|
||||
* <p>Important this is NOT equivalent with System.nanoTime().
|
||||
*
|
||||
* @param startTimestamp the explicit start timestamp of the newly created {@code Span} in nanos
|
||||
* since epoch.
|
||||
* @param startTimestamp the explicit start timestamp from the epoch of the newly created {@code
|
||||
* Span}.
|
||||
* @param unit the unit of the timestamp.
|
||||
* @return this.
|
||||
*/
|
||||
Builder setStartTimestamp(long startTimestamp);
|
||||
Builder setStartTimestamp(long startTimestamp, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Sets an explicit start timestamp for the newly created {@code Span}.
|
||||
*
|
||||
* <p>Use this method to specify an explicit start timestamp. If not called, the implementation
|
||||
* will use the timestamp value at {@link #startSpan()} time, which should be the default case.
|
||||
*
|
||||
* <p>Important this is NOT equivalent with System.nanoTime().
|
||||
*
|
||||
* @param startTimestamp the explicit start timestamp from the epoch of the newly created {@code
|
||||
* Span}.
|
||||
* @return this.
|
||||
*/
|
||||
default Builder setStartTimestamp(Instant startTimestamp) {
|
||||
if (startTimestamp == null) {
|
||||
return this;
|
||||
}
|
||||
return setStartTimestamp(
|
||||
SECONDS.toNanos(startTimestamp.getEpochSecond()) + startTimestamp.getNano(), NANOSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new {@link Span}.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class PropagatedSpanTest {
|
||||
|
|
@ -41,15 +43,18 @@ class PropagatedSpanTest {
|
|||
span.setAttribute(doubleArrayKey("NullArrayDouble"), null);
|
||||
span.setAttribute((String) null, null);
|
||||
span.addEvent("event");
|
||||
span.addEvent("event", 0);
|
||||
span.addEvent("event", 0, TimeUnit.NANOSECONDS);
|
||||
span.addEvent("event", Instant.EPOCH);
|
||||
span.addEvent("event", Attributes.of(booleanKey("MyBooleanAttributeKey"), true));
|
||||
span.addEvent("event", Attributes.of(booleanKey("MyBooleanAttributeKey"), true), 0);
|
||||
span.addEvent(
|
||||
"event", Attributes.of(booleanKey("MyBooleanAttributeKey"), true), 0, TimeUnit.NANOSECONDS);
|
||||
span.setStatus(StatusCode.OK);
|
||||
span.setStatus(StatusCode.OK, "null");
|
||||
span.recordException(new IllegalStateException());
|
||||
span.recordException(new IllegalStateException(), Attributes.empty());
|
||||
span.end();
|
||||
span.end(0);
|
||||
span.end(0, TimeUnit.NANOSECONDS);
|
||||
span.end(Instant.EPOCH);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
|
|||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.trace.Span.Kind;
|
||||
import io.opentelemetry.context.Context;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link Span.Builder}. */
|
||||
|
|
@ -32,7 +34,8 @@ class SpanBuilderTest {
|
|||
spanBuilder.setAttribute("key", .12345);
|
||||
spanBuilder.setAttribute("key", true);
|
||||
spanBuilder.setAttribute(stringKey("key"), "value");
|
||||
spanBuilder.setStartTimestamp(12345L);
|
||||
spanBuilder.setStartTimestamp(12345L, TimeUnit.NANOSECONDS);
|
||||
spanBuilder.setStartTimestamp(Instant.EPOCH);
|
||||
assertThat(spanBuilder.startSpan().getSpanContext().isValid()).isFalse();
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +50,7 @@ class SpanBuilderTest {
|
|||
Span.Builder spanBuilder = tracer.spanBuilder("MySpanName");
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> spanBuilder.setStartTimestamp(-1),
|
||||
() -> spanBuilder.setStartTimestamp(-1, TimeUnit.NANOSECONDS),
|
||||
"Negative startTimestamp");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,8 @@ class SpanConverter {
|
|||
.spanBuilder(ocSpanData.getName())
|
||||
.setStartTimestamp(
|
||||
TimeUnit.SECONDS.toNanos(ocSpanData.getStartTimestamp().getSeconds())
|
||||
+ ocSpanData.getStartTimestamp().getNanos());
|
||||
+ ocSpanData.getStartTimestamp().getNanos(),
|
||||
TimeUnit.NANOSECONDS);
|
||||
if (ocSpanData.getKind() != null) {
|
||||
builder.setSpanKind(mapKind(ocSpanData.getKind()));
|
||||
}
|
||||
|
|
@ -167,7 +168,8 @@ class SpanConverter {
|
|||
AttributeKey.longKey(MESSAGE_EVENT_ATTRIBUTE_KEY_SIZE_COMPRESSED),
|
||||
event.getEvent().getCompressedMessageSize()),
|
||||
TimeUnit.SECONDS.toNanos(event.getTimestamp().getSeconds())
|
||||
+ event.getTimestamp().getNanos());
|
||||
+ event.getTimestamp().getNanos(),
|
||||
TimeUnit.NANOSECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +192,8 @@ class SpanConverter {
|
|||
annotation.getEvent().getDescription(),
|
||||
attributesBuilder.build(),
|
||||
TimeUnit.SECONDS.toNanos(annotation.getTimestamp().getSeconds())
|
||||
+ annotation.getTimestamp().getNanos());
|
||||
+ annotation.getTimestamp().getNanos(),
|
||||
TimeUnit.NANOSECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,8 @@ class SpanConverterTest {
|
|||
"First annotation!",
|
||||
Attributes.builder().put("Attribute1", false).put("Attribute2", 123).build(),
|
||||
TimeUnit.SECONDS.toNanos(annotations.get(0).getTimestamp().getSeconds())
|
||||
+ annotations.get(0).getTimestamp().getNanos());
|
||||
+ annotations.get(0).getTimestamp().getNanos(),
|
||||
TimeUnit.NANOSECONDS);
|
||||
verify(spanSpy, times(1))
|
||||
.addEvent(
|
||||
"Second annotation!",
|
||||
|
|
@ -114,7 +115,8 @@ class SpanConverterTest {
|
|||
.put("Attribute2", "attributeValue")
|
||||
.build(),
|
||||
TimeUnit.SECONDS.toNanos(annotations.get(1).getTimestamp().getSeconds())
|
||||
+ annotations.get(1).getTimestamp().getNanos());
|
||||
+ annotations.get(1).getTimestamp().getNanos(),
|
||||
TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -145,7 +147,8 @@ class SpanConverterTest {
|
|||
.put("message.event.size.compressed", 34)
|
||||
.build(),
|
||||
TimeUnit.SECONDS.toNanos(messageEvents.get(0).getTimestamp().getSeconds())
|
||||
+ messageEvents.get(0).getTimestamp().getNanos());
|
||||
+ messageEvents.get(0).getTimestamp().getNanos(),
|
||||
TimeUnit.NANOSECONDS);
|
||||
verify(spanSpy, times(1))
|
||||
.addEvent(
|
||||
"8",
|
||||
|
|
@ -155,7 +158,8 @@ class SpanConverterTest {
|
|||
.put("message.event.size.compressed", 180)
|
||||
.build(),
|
||||
TimeUnit.SECONDS.toNanos(messageEvents.get(1).getTimestamp().getSeconds())
|
||||
+ messageEvents.get(1).getTimestamp().getNanos());
|
||||
+ messageEvents.get(1).getTimestamp().getNanos(),
|
||||
TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
private static RecordEventsSpanImpl createOpenCensusSpan() {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
|
@ -59,8 +60,9 @@ class TracezZPageHandlerTest {
|
|||
|
||||
Span runningSpan = tracer.spanBuilder(RUNNING_SPAN).startSpan();
|
||||
|
||||
Span latencySpan = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpan.end(10002);
|
||||
Span latencySpan =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpan.end(10002, TimeUnit.NANOSECONDS);
|
||||
|
||||
Span errorSpan = tracer.spanBuilder(ERROR_SPAN).startSpan();
|
||||
errorSpan.setStatus(StatusCode.ERROR);
|
||||
|
|
@ -142,32 +144,41 @@ class TracezZPageHandlerTest {
|
|||
void summaryTable_linkForLatencyBasedSpans_OnePerBoundary() {
|
||||
OutputStream output = new ByteArrayOutputStream();
|
||||
// Boundary 0, >1us
|
||||
Span latencySpanSubtype0 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpanSubtype0.end(1002);
|
||||
Span latencySpanSubtype0 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpanSubtype0.end(1002, TimeUnit.NANOSECONDS);
|
||||
// Boundary 1, >10us
|
||||
Span latencySpanSubtype1 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpanSubtype1.end(10002);
|
||||
Span latencySpanSubtype1 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpanSubtype1.end(10002, TimeUnit.NANOSECONDS);
|
||||
// Boundary 2, >100us
|
||||
Span latencySpanSubtype2 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpanSubtype2.end(100002);
|
||||
Span latencySpanSubtype2 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpanSubtype2.end(100002, TimeUnit.NANOSECONDS);
|
||||
// Boundary 3, >1ms
|
||||
Span latencySpanSubtype3 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpanSubtype3.end(1000002);
|
||||
Span latencySpanSubtype3 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpanSubtype3.end(1000002, TimeUnit.NANOSECONDS);
|
||||
// Boundary 4, >10ms
|
||||
Span latencySpanSubtype4 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpanSubtype4.end(10000002);
|
||||
Span latencySpanSubtype4 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpanSubtype4.end(10000002, TimeUnit.NANOSECONDS);
|
||||
// Boundary 5, >100ms
|
||||
Span latencySpanSubtype5 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpanSubtype5.end(100000002);
|
||||
Span latencySpanSubtype5 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpanSubtype5.end(100000002, TimeUnit.NANOSECONDS);
|
||||
// Boundary 6, >1s
|
||||
Span latencySpanSubtype6 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpanSubtype6.end(1000000002);
|
||||
Span latencySpanSubtype6 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpanSubtype6.end(1000000002, TimeUnit.NANOSECONDS);
|
||||
// Boundary 7, >10s
|
||||
Span latencySpanSubtype7 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpanSubtype7.end(10000000002L);
|
||||
Span latencySpanSubtype7 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpanSubtype7.end(10000000002L, TimeUnit.NANOSECONDS);
|
||||
// Boundary 8, >100s
|
||||
Span latencySpanSubtype8 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpanSubtype8.end(100000000002L);
|
||||
Span latencySpanSubtype8 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpanSubtype8.end(100000000002L, TimeUnit.NANOSECONDS);
|
||||
|
||||
TracezZPageHandler tracezZPageHandler = new TracezZPageHandler(dataAggregator);
|
||||
tracezZPageHandler.emitHtml(emptyQueryMap, output);
|
||||
|
|
@ -205,14 +216,18 @@ class TracezZPageHandlerTest {
|
|||
void summaryTable_linkForLatencyBasedSpans_MultipleForOneBoundary() {
|
||||
OutputStream output = new ByteArrayOutputStream();
|
||||
// 4 samples in boundary 5, >100ms
|
||||
Span latencySpan100ms1 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpan100ms1.end(112931232L);
|
||||
Span latencySpan100ms2 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpan100ms2.end(138694322L);
|
||||
Span latencySpan100ms3 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpan100ms3.end(154486482L);
|
||||
Span latencySpan100ms4 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpan100ms4.end(194892582L);
|
||||
Span latencySpan100ms1 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpan100ms1.end(112931232L, TimeUnit.NANOSECONDS);
|
||||
Span latencySpan100ms2 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpan100ms2.end(138694322L, TimeUnit.NANOSECONDS);
|
||||
Span latencySpan100ms3 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpan100ms3.end(154486482L, TimeUnit.NANOSECONDS);
|
||||
Span latencySpan100ms4 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpan100ms4.end(194892582L, TimeUnit.NANOSECONDS);
|
||||
|
||||
TracezZPageHandler tracezZPageHandler = new TracezZPageHandler(dataAggregator);
|
||||
tracezZPageHandler.emitHtml(emptyQueryMap, output);
|
||||
|
|
@ -270,10 +285,12 @@ class TracezZPageHandlerTest {
|
|||
@Test
|
||||
void spanDetails_emitLatencySpanDetailsCorrectly() {
|
||||
OutputStream output = new ByteArrayOutputStream();
|
||||
Span latencySpan1 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpan1.end(10002);
|
||||
Span latencySpan2 = tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L).startSpan();
|
||||
latencySpan2.end(10002);
|
||||
Span latencySpan1 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpan1.end(10002, TimeUnit.NANOSECONDS);
|
||||
Span latencySpan2 =
|
||||
tracer.spanBuilder(LATENCY_SPAN).setStartTimestamp(1L, TimeUnit.NANOSECONDS).startSpan();
|
||||
latencySpan2.end(10002, TimeUnit.NANOSECONDS);
|
||||
Map<String, String> queryMap =
|
||||
ImmutableMap.of("zspanname", LATENCY_SPAN, "ztype", "1", "zsubtype", "1");
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import java.io.StringWriter;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nonnull;
|
||||
|
|
@ -317,11 +318,11 @@ final class RecordEventsReadableSpan implements ReadWriteSpan {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ReadWriteSpan addEvent(String name, long timestamp) {
|
||||
public ReadWriteSpan addEvent(String name, long timestamp, TimeUnit unit) {
|
||||
if (name == null) {
|
||||
return this;
|
||||
}
|
||||
addTimedEvent(Event.create(timestamp, name, Attributes.empty(), 0));
|
||||
addTimedEvent(Event.create(unit.toNanos(timestamp), name, Attributes.empty(), 0));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -341,14 +342,14 @@ final class RecordEventsReadableSpan implements ReadWriteSpan {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ReadWriteSpan addEvent(String name, Attributes attributes, long timestamp) {
|
||||
public ReadWriteSpan addEvent(String name, Attributes attributes, long timestamp, TimeUnit unit) {
|
||||
if (name == null) {
|
||||
return this;
|
||||
}
|
||||
int totalAttributeCount = attributes.size();
|
||||
addTimedEvent(
|
||||
Event.create(
|
||||
timestamp,
|
||||
unit.toNanos(timestamp),
|
||||
name,
|
||||
copyAndLimitAttributes(attributes, traceConfig.getMaxNumberOfAttributesPerEvent()),
|
||||
totalAttributeCount));
|
||||
|
|
@ -408,7 +409,7 @@ final class RecordEventsReadableSpan implements ReadWriteSpan {
|
|||
if (exception == null) {
|
||||
return this;
|
||||
}
|
||||
long timestamp = clock.now();
|
||||
long timestampNanos = clock.now();
|
||||
|
||||
Attributes.Builder attributes = Attributes.builder();
|
||||
attributes.put(SemanticAttributes.EXCEPTION_TYPE, exception.getClass().getCanonicalName());
|
||||
|
|
@ -423,7 +424,11 @@ final class RecordEventsReadableSpan implements ReadWriteSpan {
|
|||
attributes.putAll(additionalAttributes);
|
||||
}
|
||||
|
||||
addEvent(SemanticAttributes.EXCEPTION_EVENT_NAME, attributes.build(), timestamp);
|
||||
addEvent(
|
||||
SemanticAttributes.EXCEPTION_EVENT_NAME,
|
||||
attributes.build(),
|
||||
timestampNanos,
|
||||
TimeUnit.NANOSECONDS);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -448,8 +453,11 @@ final class RecordEventsReadableSpan implements ReadWriteSpan {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void end(long timestamp) {
|
||||
endInternal(timestamp == 0 ? clock.now() : timestamp);
|
||||
public void end(long timestamp, TimeUnit unit) {
|
||||
if (unit == null) {
|
||||
unit = TimeUnit.NANOSECONDS;
|
||||
}
|
||||
endInternal(timestamp == 0 ? clock.now() : unit.toNanos(timestamp));
|
||||
}
|
||||
|
||||
private void endInternal(long endEpochNanos) {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** {@link SpanBuilderSdk} is SDK implementation of {@link Span.Builder}. */
|
||||
|
|
@ -165,9 +166,9 @@ final class SpanBuilderSdk implements Span.Builder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Span.Builder setStartTimestamp(long startTimestamp) {
|
||||
public Span.Builder setStartTimestamp(long startTimestamp, TimeUnit unit) {
|
||||
Utils.checkArgument(startTimestamp >= 0, "Negative startTimestamp");
|
||||
startEpochNanos = startTimestamp;
|
||||
startEpochNanos = unit.toNanos(startTimestamp);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import io.opentelemetry.sdk.trace.data.SpanData.Link;
|
|||
import io.opentelemetry.sdk.trace.data.SpanData.Status;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -481,11 +482,62 @@ class RecordEventsReadableSpanTest {
|
|||
try {
|
||||
span.addEvent("event1");
|
||||
span.addEvent("event2", Attributes.of(stringKey("e1key"), "e1Value"));
|
||||
span.addEvent("event3", 10, TimeUnit.SECONDS);
|
||||
span.addEvent("event4", Instant.ofEpochSecond(20));
|
||||
span.addEvent(
|
||||
"event5", Attributes.builder().put("foo", "bar").build(), 30, TimeUnit.MILLISECONDS);
|
||||
span.addEvent(
|
||||
"event6", Attributes.builder().put("foo", "bar").build(), Instant.ofEpochMilli(1000));
|
||||
} finally {
|
||||
span.end();
|
||||
}
|
||||
List<Event> events = span.toSpanData().getEvents();
|
||||
assertThat(events.size()).isEqualTo(2);
|
||||
assertThat(events).hasSize(6);
|
||||
assertThat(events.get(0))
|
||||
.satisfies(
|
||||
event -> {
|
||||
assertThat(event.getName()).isEqualTo("event1");
|
||||
assertThat(event.getAttributes()).isEqualTo(Attributes.empty());
|
||||
assertThat(event.getEpochNanos()).isEqualTo(START_EPOCH_NANOS);
|
||||
});
|
||||
assertThat(events.get(1))
|
||||
.satisfies(
|
||||
event -> {
|
||||
assertThat(event.getName()).isEqualTo("event2");
|
||||
assertThat(event.getAttributes())
|
||||
.isEqualTo(Attributes.of(stringKey("e1key"), "e1Value"));
|
||||
assertThat(event.getEpochNanos()).isEqualTo(START_EPOCH_NANOS);
|
||||
});
|
||||
assertThat(events.get(2))
|
||||
.satisfies(
|
||||
event -> {
|
||||
assertThat(event.getName()).isEqualTo("event3");
|
||||
assertThat(event.getAttributes()).isEqualTo(Attributes.empty());
|
||||
assertThat(event.getEpochNanos()).isEqualTo(TimeUnit.SECONDS.toNanos(10));
|
||||
});
|
||||
assertThat(events.get(3))
|
||||
.satisfies(
|
||||
event -> {
|
||||
assertThat(event.getName()).isEqualTo("event4");
|
||||
assertThat(event.getAttributes()).isEqualTo(Attributes.empty());
|
||||
assertThat(event.getEpochNanos()).isEqualTo(TimeUnit.SECONDS.toNanos(20));
|
||||
});
|
||||
assertThat(events.get(4))
|
||||
.satisfies(
|
||||
event -> {
|
||||
assertThat(event.getName()).isEqualTo("event5");
|
||||
assertThat(event.getAttributes())
|
||||
.isEqualTo(Attributes.builder().put("foo", "bar").build());
|
||||
assertThat(event.getEpochNanos()).isEqualTo(TimeUnit.MILLISECONDS.toNanos(30));
|
||||
});
|
||||
assertThat(events.get(5))
|
||||
.satisfies(
|
||||
event -> {
|
||||
assertThat(event.getName()).isEqualTo("event6");
|
||||
assertThat(event.getAttributes())
|
||||
.isEqualTo(Attributes.builder().put("foo", "bar").build());
|
||||
assertThat(event.getEpochNanos()).isEqualTo(TimeUnit.MILLISECONDS.toNanos(1000));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -511,6 +563,20 @@ class RecordEventsReadableSpanTest {
|
|||
assertThat(spanData.getTotalAttributeCount()).isEqualTo(2 * maxNumberOfAttributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
void endWithTimestamp_numeric() {
|
||||
RecordEventsReadableSpan span1 = createTestRootSpan();
|
||||
span1.end(10, TimeUnit.NANOSECONDS);
|
||||
assertThat(span1.toSpanData().getEndEpochNanos()).isEqualTo(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
void endWithTimestamp_instant() {
|
||||
RecordEventsReadableSpan span1 = createTestRootSpan();
|
||||
span1.end(Instant.ofEpochMilli(10));
|
||||
assertThat(span1.toSpanData().getEndEpochNanos()).isEqualTo(TimeUnit.MILLISECONDS.toNanos(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void droppingAndAddingAttributes() {
|
||||
final int maxNumberOfAttributes = 8;
|
||||
|
|
@ -690,11 +756,15 @@ class RecordEventsReadableSpanTest {
|
|||
span.setStatus(null, null);
|
||||
span.updateName(null);
|
||||
span.addEvent(null);
|
||||
span.addEvent(null, 0);
|
||||
span.addEvent(null, null);
|
||||
span.addEvent(null, null, 0);
|
||||
span.addEvent(null, 0, null);
|
||||
span.addEvent(null, (Attributes) null);
|
||||
span.addEvent(null, (Instant) null);
|
||||
span.addEvent(null, null, 0, null);
|
||||
span.addEvent(null, null, null);
|
||||
span.recordException(null);
|
||||
span.end(0);
|
||||
span.end(0, TimeUnit.NANOSECONDS);
|
||||
span.end(1, null);
|
||||
span.end(null);
|
||||
|
||||
// Ignored the bad calls
|
||||
SpanData data = span.toSpanData();
|
||||
|
|
|
|||
|
|
@ -34,9 +34,11 @@ import io.opentelemetry.sdk.trace.data.SpanData;
|
|||
import io.opentelemetry.sdk.trace.data.SpanData.Link;
|
||||
import io.opentelemetry.sdk.trace.samplers.Sampler;
|
||||
import io.opentelemetry.sdk.trace.samplers.SamplingResult;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
@ -793,11 +795,36 @@ class SpanBuilderSdkTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void startTimestamp_numeric() {
|
||||
RecordEventsReadableSpan span =
|
||||
(RecordEventsReadableSpan)
|
||||
tracerSdk
|
||||
.spanBuilder(SPAN_NAME)
|
||||
.setStartTimestamp(10, TimeUnit.NANOSECONDS)
|
||||
.startSpan();
|
||||
span.end();
|
||||
assertThat(span.toSpanData().getStartEpochNanos()).isEqualTo(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
void startTimestamp_instant() {
|
||||
RecordEventsReadableSpan span =
|
||||
(RecordEventsReadableSpan)
|
||||
tracerSdk
|
||||
.spanBuilder(SPAN_NAME)
|
||||
.setStartTimestamp(Instant.ofEpochMilli(100))
|
||||
.startSpan();
|
||||
span.end();
|
||||
assertThat(span.toSpanData().getStartEpochNanos())
|
||||
.isEqualTo(TimeUnit.MILLISECONDS.toNanos(100));
|
||||
}
|
||||
|
||||
@Test
|
||||
void startTimestamp_null() {
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> tracerSdk.spanBuilder(SPAN_NAME).setStartTimestamp(-1),
|
||||
() -> tracerSdk.spanBuilder(SPAN_NAME).setStartTimestamp(-1, TimeUnit.NANOSECONDS),
|
||||
"Negative startTimestamp");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue