From f0e78ba5a10165cce2b63809bfdfe3e34b1eb456 Mon Sep 17 00:00:00 2001 From: Bogdan Drutu Date: Sat, 22 Sep 2018 09:37:29 -0700 Subject: Split SpanImpl into record/notrecord span impl to avoid checks of recording all time. (#1468) * Split SpanImpl into record/notrecord span impl to avoid checks of recording all time. * Remove one extra SuppressWarnings. --- .../implcore/trace/NoRecordEventsSpanImpl.java | 85 +++ .../implcore/trace/RecordEventsSpanImpl.java | 579 +++++++++++++++++++ .../opencensus/implcore/trace/SpanBuilderImpl.java | 46 +- .../io/opencensus/implcore/trace/SpanImpl.java | 619 -------------------- .../implcore/trace/StartEndHandlerImpl.java | 14 +- .../implcore/trace/TraceComponentImplBase.java | 2 +- .../io/opencensus/implcore/trace/TracerImpl.java | 4 +- .../export/InProcessRunningSpanStoreImpl.java | 18 +- .../export/InProcessSampledSpanStoreImpl.java | 56 +- .../trace/export/RunningSpanStoreImpl.java | 13 +- .../trace/export/SampledSpanStoreImpl.java | 10 +- .../implcore/trace/export/SpanExporterImpl.java | 22 +- .../implcore/trace/NoRecordEventsSpanImplTest.java | 91 +++ .../implcore/trace/RecordEventsSpanImplTest.java | 594 +++++++++++++++++++ .../implcore/trace/SpanBuilderImplTest.java | 90 ++- .../io/opencensus/implcore/trace/SpanImplTest.java | 639 --------------------- .../opencensus/implcore/trace/TracerImplTest.java | 2 +- .../export/InProcessRunningSpanStoreImplTest.java | 32 +- .../export/InProcessSampledSpanStoreImplTest.java | 51 +- .../trace/export/NoopRunningSpanStoreImplTest.java | 18 +- .../trace/export/NoopSampledSpanStoreImplTest.java | 18 +- .../trace/export/SpanExporterImplTest.java | 53 +- 22 files changed, 1579 insertions(+), 1477 deletions(-) create mode 100644 impl_core/src/main/java/io/opencensus/implcore/trace/NoRecordEventsSpanImpl.java create mode 100644 impl_core/src/main/java/io/opencensus/implcore/trace/RecordEventsSpanImpl.java delete mode 100644 impl_core/src/main/java/io/opencensus/implcore/trace/SpanImpl.java create mode 100644 impl_core/src/test/java/io/opencensus/implcore/trace/NoRecordEventsSpanImplTest.java create mode 100644 impl_core/src/test/java/io/opencensus/implcore/trace/RecordEventsSpanImplTest.java delete mode 100644 impl_core/src/test/java/io/opencensus/implcore/trace/SpanImplTest.java diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/NoRecordEventsSpanImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/NoRecordEventsSpanImpl.java new file mode 100644 index 00000000..8a5f8e05 --- /dev/null +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/NoRecordEventsSpanImpl.java @@ -0,0 +1,85 @@ +/* + * Copyright 2018, OpenCensus 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.opencensus.implcore.trace; + +import com.google.common.base.Preconditions; +import io.opencensus.trace.Annotation; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.EndSpanOptions; +import io.opencensus.trace.Link; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.Status; +import java.util.EnumSet; +import java.util.Map; + +/** Implementation for the {@link Span} class that does not record trace events. */ +final class NoRecordEventsSpanImpl extends Span { + + private static final EnumSet NOT_RECORD_EVENTS_SPAN_OPTIONS = + EnumSet.noneOf(Span.Options.class); + + static NoRecordEventsSpanImpl create(SpanContext context) { + return new NoRecordEventsSpanImpl(context); + } + + @Override + public void addAnnotation(String description, Map attributes) { + Preconditions.checkNotNull(description, "description"); + Preconditions.checkNotNull(attributes, "attribute"); + } + + @Override + public void addAnnotation(Annotation annotation) { + Preconditions.checkNotNull(annotation, "annotation"); + } + + @Override + public void putAttribute(String key, AttributeValue value) { + Preconditions.checkNotNull(key, "key"); + Preconditions.checkNotNull(value, "value"); + } + + @Override + public void putAttributes(Map attributes) { + Preconditions.checkNotNull(attributes, "attributes"); + } + + @Override + public void addMessageEvent(io.opencensus.trace.MessageEvent messageEvent) { + Preconditions.checkNotNull(messageEvent, "messageEvent"); + } + + @Override + public void addLink(Link link) { + Preconditions.checkNotNull(link, "link"); + } + + @Override + public void setStatus(Status status) { + Preconditions.checkNotNull(status, "status"); + } + + @Override + public void end(EndSpanOptions options) { + Preconditions.checkNotNull(options, "options"); + } + + private NoRecordEventsSpanImpl(SpanContext context) { + super(context, NOT_RECORD_EVENTS_SPAN_OPTIONS); + } +} diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/RecordEventsSpanImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/RecordEventsSpanImpl.java new file mode 100644 index 00000000..af3545bc --- /dev/null +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/RecordEventsSpanImpl.java @@ -0,0 +1,579 @@ +/* + * Copyright 2017, OpenCensus 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.opencensus.implcore.trace; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.EvictingQueue; +import io.opencensus.common.Clock; +import io.opencensus.implcore.internal.CheckerFrameworkUtils; +import io.opencensus.implcore.internal.TimestampConverter; +import io.opencensus.implcore.trace.internal.ConcurrentIntrusiveList.Element; +import io.opencensus.trace.Annotation; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.EndSpanOptions; +import io.opencensus.trace.Link; +import io.opencensus.trace.Span; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.Status; +import io.opencensus.trace.Tracer; +import io.opencensus.trace.config.TraceParams; +import io.opencensus.trace.export.SpanData; +import io.opencensus.trace.export.SpanData.TimedEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.ThreadSafe; + +// TODO(hailongwen): remove the usage of `NetworkEvent` in the future. +/** Implementation for the {@link Span} class that records trace events. */ +@ThreadSafe +public final class RecordEventsSpanImpl extends Span implements Element { + private static final Logger logger = Logger.getLogger(Tracer.class.getName()); + + private static final EnumSet RECORD_EVENTS_SPAN_OPTIONS = + EnumSet.of(Span.Options.RECORD_EVENTS); + + // The parent SpanId of this span. Null if this is a root span. + @Nullable private final SpanId parentSpanId; + // True if the parent is on a different process. + @Nullable private final Boolean hasRemoteParent; + // Active trace params when the Span was created. + private final TraceParams traceParams; + // Handler called when the span starts and ends. + private final StartEndHandler startEndHandler; + // The displayed name of the span. + private final String name; + // The kind of the span. + @Nullable private final Kind kind; + // The clock used to get the time. + private final Clock clock; + // The time converter used to convert nano time to Timestamp. This is needed because Java has + // millisecond granularity for Timestamp and tracing events are recorded more often. + @Nullable private final TimestampConverter timestampConverter; + // The start time of the span. + private final long startNanoTime; + // Set of recorded attributes. DO NOT CALL any other method that changes the ordering of events. + @GuardedBy("this") + @Nullable + private AttributesWithCapacity attributes; + // List of recorded annotations. + @GuardedBy("this") + @Nullable + private TraceEvents> annotations; + // List of recorded network events. + @GuardedBy("this") + @Nullable + private TraceEvents> messageEvents; + // List of recorded links to parent and child spans. + @GuardedBy("this") + @Nullable + private TraceEvents links; + // The status of the span. + @GuardedBy("this") + @Nullable + private Status status; + // The end time of the span. + @GuardedBy("this") + private long endNanoTime; + // True if the span is ended. + @GuardedBy("this") + private boolean hasBeenEnded; + + @GuardedBy("this") + private boolean sampleToLocalSpanStore; + + // Pointers for the ConcurrentIntrusiveList$Element. Guarded by the ConcurrentIntrusiveList. + @Nullable private RecordEventsSpanImpl next = null; + @Nullable private RecordEventsSpanImpl prev = null; + + /** + * Creates and starts a span with the given configuration. + * + * @param context supplies the trace_id and span_id for the newly started span. + * @param name the displayed name for the new span. + * @param parentSpanId the span_id of the parent span, or null if the new span is a root span. + * @param hasRemoteParent {@code true} if the parentContext is remote. {@code null} if this is a + * root span. + * @param traceParams trace parameters like sampler and probability. + * @param startEndHandler handler called when the span starts and ends. + * @param timestampConverter null if the span is a root span or the parent is not sampled. If the + * parent is sampled, we should use the same converter to ensure ordering between tracing + * events. + * @param clock the clock used to get the time. + * @return a new and started span. + */ + @VisibleForTesting + public static RecordEventsSpanImpl startSpan( + SpanContext context, + String name, + @Nullable Kind kind, + @Nullable SpanId parentSpanId, + @Nullable Boolean hasRemoteParent, + TraceParams traceParams, + StartEndHandler startEndHandler, + @Nullable TimestampConverter timestampConverter, + Clock clock) { + RecordEventsSpanImpl span = + new RecordEventsSpanImpl( + context, + name, + kind, + parentSpanId, + hasRemoteParent, + traceParams, + startEndHandler, + timestampConverter, + clock); + // Call onStart here instead of calling in the constructor to make sure the span is completely + // initialized. + startEndHandler.onStart(span); + return span; + } + + /** + * Returns the name of the {@code Span}. + * + * @return the name of the {@code Span}. + */ + public String getName() { + return name; + } + + /** + * Returns the status of the {@code Span}. If not set defaults to {@link Status#OK}. + * + * @return the status of the {@code Span}. + */ + public Status getStatus() { + synchronized (this) { + return getStatusWithDefault(); + } + } + + /** + * Returns the end nano time (see {@link System#nanoTime()}). If the current {@code Span} is not + * ended then returns {@link Clock#nowNanos()}. + * + * @return the end nano time. + */ + public long getEndNanoTime() { + synchronized (this) { + return hasBeenEnded ? endNanoTime : clock.nowNanos(); + } + } + + /** + * Returns the latency of the {@code Span} in nanos. If still active then returns now() - start + * time. + * + * @return the latency of the {@code Span} in nanos. + */ + public long getLatencyNs() { + synchronized (this) { + return hasBeenEnded ? endNanoTime - startNanoTime : clock.nowNanos() - startNanoTime; + } + } + + /** + * Returns if the name of this {@code Span} must be register to the {@code SampledSpanStore}. + * + * @return if the name of this {@code Span} must be register to the {@code SampledSpanStore}. + */ + public boolean getSampleToLocalSpanStore() { + synchronized (this) { + checkState(hasBeenEnded, "Running span does not have the SampleToLocalSpanStore set."); + return sampleToLocalSpanStore; + } + } + + /** + * Returns the kind of this {@code Span}. + * + * @return the kind of this {@code Span}. + */ + @Nullable + public Kind getKind() { + return kind; + } + + /** + * Returns the {@code TimestampConverter} used by this {@code Span}. + * + * @return the {@code TimestampConverter} used by this {@code Span}. + */ + @Nullable + TimestampConverter getTimestampConverter() { + return timestampConverter; + } + + /** + * Returns an immutable representation of all the data from this {@code Span}. + * + * @return an immutable representation of all the data from this {@code Span}. + * @throws IllegalStateException if the Span doesn't have RECORD_EVENTS option. + */ + public SpanData toSpanData() { + synchronized (this) { + SpanData.Attributes attributesSpanData = + attributes == null + ? SpanData.Attributes.create(Collections.emptyMap(), 0) + : SpanData.Attributes.create(attributes, attributes.getNumberOfDroppedAttributes()); + SpanData.TimedEvents annotationsSpanData = + createTimedEvents(getInitializedAnnotations(), timestampConverter); + SpanData.TimedEvents messageEventsSpanData = + createTimedEvents(getInitializedNetworkEvents(), timestampConverter); + SpanData.Links linksSpanData = + links == null + ? SpanData.Links.create(Collections.emptyList(), 0) + : SpanData.Links.create( + new ArrayList(links.events), links.getNumberOfDroppedEvents()); + return SpanData.create( + getContext(), + parentSpanId, + hasRemoteParent, + name, + kind, + CheckerFrameworkUtils.castNonNull(timestampConverter).convertNanoTime(startNanoTime), + attributesSpanData, + annotationsSpanData, + messageEventsSpanData, + linksSpanData, + null, // Not supported yet. + hasBeenEnded ? getStatusWithDefault() : null, + hasBeenEnded + ? CheckerFrameworkUtils.castNonNull(timestampConverter).convertNanoTime(endNanoTime) + : null); + } + } + + @Override + public void putAttribute(String key, AttributeValue value) { + Preconditions.checkNotNull(key, "key"); + Preconditions.checkNotNull(value, "value"); + synchronized (this) { + if (hasBeenEnded) { + logger.log(Level.FINE, "Calling putAttributes() on an ended Span."); + return; + } + getInitializedAttributes().putAttribute(key, value); + } + } + + @Override + public void putAttributes(Map attributes) { + Preconditions.checkNotNull(attributes, "attributes"); + synchronized (this) { + if (hasBeenEnded) { + logger.log(Level.FINE, "Calling putAttributes() on an ended Span."); + return; + } + getInitializedAttributes().putAttributes(attributes); + } + } + + @Override + public void addAnnotation(String description, Map attributes) { + Preconditions.checkNotNull(description, "description"); + Preconditions.checkNotNull(attributes, "attribute"); + synchronized (this) { + if (hasBeenEnded) { + logger.log(Level.FINE, "Calling addAnnotation() on an ended Span."); + return; + } + getInitializedAnnotations() + .addEvent( + new EventWithNanoTime( + clock.nowNanos(), + Annotation.fromDescriptionAndAttributes(description, attributes))); + } + } + + @Override + public void addAnnotation(Annotation annotation) { + Preconditions.checkNotNull(annotation, "annotation"); + synchronized (this) { + if (hasBeenEnded) { + logger.log(Level.FINE, "Calling addAnnotation() on an ended Span."); + return; + } + getInitializedAnnotations() + .addEvent(new EventWithNanoTime(clock.nowNanos(), annotation)); + } + } + + @Override + public void addMessageEvent(io.opencensus.trace.MessageEvent messageEvent) { + Preconditions.checkNotNull(messageEvent, "messageEvent"); + synchronized (this) { + if (hasBeenEnded) { + logger.log(Level.FINE, "Calling addNetworkEvent() on an ended Span."); + return; + } + getInitializedNetworkEvents() + .addEvent( + new EventWithNanoTime( + clock.nowNanos(), checkNotNull(messageEvent, "networkEvent"))); + } + } + + @Override + public void addLink(Link link) { + Preconditions.checkNotNull(link, "link"); + synchronized (this) { + if (hasBeenEnded) { + logger.log(Level.FINE, "Calling addLink() on an ended Span."); + return; + } + getInitializedLinks().addEvent(link); + } + } + + @Override + public void setStatus(Status status) { + Preconditions.checkNotNull(status, "status"); + synchronized (this) { + if (hasBeenEnded) { + logger.log(Level.FINE, "Calling setStatus() on an ended Span."); + return; + } + this.status = status; + } + } + + @Override + public void end(EndSpanOptions options) { + Preconditions.checkNotNull(options, "options"); + synchronized (this) { + if (hasBeenEnded) { + logger.log(Level.FINE, "Calling end() on an ended Span."); + return; + } + if (options.getStatus() != null) { + status = options.getStatus(); + } + sampleToLocalSpanStore = options.getSampleToLocalSpanStore(); + endNanoTime = clock.nowNanos(); + hasBeenEnded = true; + } + startEndHandler.onEnd(this); + } + + @GuardedBy("this") + private AttributesWithCapacity getInitializedAttributes() { + if (attributes == null) { + attributes = new AttributesWithCapacity(traceParams.getMaxNumberOfAttributes()); + } + return attributes; + } + + @GuardedBy("this") + private TraceEvents> getInitializedAnnotations() { + if (annotations == null) { + annotations = + new TraceEvents>(traceParams.getMaxNumberOfAnnotations()); + } + return annotations; + } + + @GuardedBy("this") + private TraceEvents> + getInitializedNetworkEvents() { + if (messageEvents == null) { + messageEvents = + new TraceEvents>( + traceParams.getMaxNumberOfMessageEvents()); + } + return messageEvents; + } + + @GuardedBy("this") + private TraceEvents getInitializedLinks() { + if (links == null) { + links = new TraceEvents(traceParams.getMaxNumberOfLinks()); + } + return links; + } + + @GuardedBy("this") + private Status getStatusWithDefault() { + return status == null ? Status.OK : status; + } + + private static SpanData.TimedEvents createTimedEvents( + TraceEvents> events, @Nullable TimestampConverter timestampConverter) { + if (events == null) { + return SpanData.TimedEvents.create(Collections.>emptyList(), 0); + } + List> eventsList = new ArrayList>(events.events.size()); + for (EventWithNanoTime networkEvent : events.events) { + eventsList.add( + networkEvent.toSpanDataTimedEvent(CheckerFrameworkUtils.castNonNull(timestampConverter))); + } + return SpanData.TimedEvents.create(eventsList, events.getNumberOfDroppedEvents()); + } + + @Override + @Nullable + public RecordEventsSpanImpl getNext() { + return next; + } + + @Override + public void setNext(@Nullable RecordEventsSpanImpl element) { + next = element; + } + + @Override + @Nullable + public RecordEventsSpanImpl getPrev() { + return prev; + } + + @Override + public void setPrev(@Nullable RecordEventsSpanImpl element) { + prev = element; + } + + /** + * Interface to handle the start and end operations for a {@link Span} only when the {@code Span} + * has {@link Options#RECORD_EVENTS} option. + * + *

Implementation must avoid high overhead work in any of the methods because the code is + * executed on the critical path. + * + *

One instance can be called by multiple threads in the same time, so the implementation must + * be thread-safe. + */ + public interface StartEndHandler { + void onStart(RecordEventsSpanImpl span); + + void onEnd(RecordEventsSpanImpl span); + } + + // A map implementation with a fixed capacity that drops events when the map gets full. Eviction + // is based on the access order. + private static final class AttributesWithCapacity extends LinkedHashMap { + private final int capacity; + private int totalRecordedAttributes = 0; + // Here because -Werror complains about this: [serial] serializable class AttributesWithCapacity + // has no definition of serialVersionUID. This class shouldn't be serialized. + private static final long serialVersionUID = 42L; + + private AttributesWithCapacity(int capacity) { + // Capacity of the map is capacity + 1 to avoid resizing because removeEldestEntry is invoked + // by put and putAll after inserting a new entry into the map. The loadFactor is set to 1 + // to avoid resizing because. The accessOrder is set to true. + super(capacity + 1, 1, /*accessOrder=*/ true); + this.capacity = capacity; + } + + // Users must call this method instead of put to keep count of the total number of entries + // inserted. + private void putAttribute(String key, AttributeValue value) { + totalRecordedAttributes += 1; + put(key, value); + } + + // Users must call this method instead of putAll to keep count of the total number of entries + // inserted. + private void putAttributes(Map attributes) { + totalRecordedAttributes += attributes.size(); + putAll(attributes); + } + + private int getNumberOfDroppedAttributes() { + return totalRecordedAttributes - size(); + } + + // It is called after each put or putAll call in order to determine if the eldest inserted + // entry should be removed or not. + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > this.capacity; + } + } + + private static final class TraceEvents { + private int totalRecordedEvents = 0; + private final EvictingQueue events; + + private int getNumberOfDroppedEvents() { + return totalRecordedEvents - events.size(); + } + + TraceEvents(int maxNumEvents) { + events = EvictingQueue.create(maxNumEvents); + } + + void addEvent(T event) { + totalRecordedEvents++; + events.add(event); + } + } + + // Timed event that uses nanoTime to represent the Timestamp. + private static final class EventWithNanoTime { + private final long nanoTime; + private final T event; + + private EventWithNanoTime(long nanoTime, T event) { + this.nanoTime = nanoTime; + this.event = event; + } + + private TimedEvent toSpanDataTimedEvent(TimestampConverter timestampConverter) { + return TimedEvent.create(timestampConverter.convertNanoTime(nanoTime), event); + } + } + + private RecordEventsSpanImpl( + SpanContext context, + String name, + @Nullable Kind kind, + @Nullable SpanId parentSpanId, + @Nullable Boolean hasRemoteParent, + TraceParams traceParams, + StartEndHandler startEndHandler, + @Nullable TimestampConverter timestampConverter, + Clock clock) { + super(context, RECORD_EVENTS_SPAN_OPTIONS); + this.parentSpanId = parentSpanId; + this.hasRemoteParent = hasRemoteParent; + this.name = name; + this.kind = kind; + this.traceParams = traceParams; + this.startEndHandler = startEndHandler; + this.clock = clock; + this.hasBeenEnded = false; + this.sampleToLocalSpanStore = false; + this.timestampConverter = + timestampConverter != null ? timestampConverter : TimestampConverter.now(clock); + startNanoTime = clock.nowNanos(); + } +} diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/SpanBuilderImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/SpanBuilderImpl.java index 3ea0ce33..5565e9de 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/SpanBuilderImpl.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/SpanBuilderImpl.java @@ -35,7 +35,6 @@ import io.opencensus.trace.Tracestate; import io.opencensus.trace.config.TraceConfig; import io.opencensus.trace.config.TraceParams; import java.util.Collections; -import java.util.EnumSet; import java.util.List; import java.util.Random; import javax.annotation.Nullable; @@ -49,11 +48,6 @@ final class SpanBuilderImpl extends SpanBuilder { private static final TraceOptions NOT_SAMPLED_TRACE_OPTIONS = TraceOptions.builder().setIsSampled(false).build(); - private static final EnumSet NOT_RECORD_EVENTS_SPAN_OPTIONS = - EnumSet.noneOf(Span.Options.class); - private static final EnumSet RECORD_EVENTS_SPAN_OPTIONS = - EnumSet.of(Span.Options.RECORD_EVENTS); - private final Options options; private final String name; @Nullable private final Span parent; @@ -63,7 +57,7 @@ final class SpanBuilderImpl extends SpanBuilder { @Nullable private Boolean recordEvents; @Nullable private Kind kind; - private SpanImpl startSpanInternal( + private Span startSpanInternal( @Nullable SpanContext parent, @Nullable Boolean hasRemoteParent, String name, @@ -102,22 +96,20 @@ final class SpanBuilderImpl extends SpanBuilder { activeTraceParams) ? SAMPLED_TRACE_OPTIONS : NOT_SAMPLED_TRACE_OPTIONS; - EnumSet spanOptions = + Span span = (traceOptions.isSampled() || Boolean.TRUE.equals(recordEvents)) - ? RECORD_EVENTS_SPAN_OPTIONS - : NOT_RECORD_EVENTS_SPAN_OPTIONS; - SpanImpl span = - SpanImpl.startSpan( - SpanContext.create(traceId, spanId, traceOptions, tracestate), - spanOptions, - name, - kind, - parentSpanId, - hasRemoteParent, - activeTraceParams, - options.startEndHandler, - timestampConverter, - options.clock); + ? RecordEventsSpanImpl.startSpan( + SpanContext.create(traceId, spanId, traceOptions, tracestate), + name, + kind, + parentSpanId, + hasRemoteParent, + activeTraceParams, + options.startEndHandler, + timestampConverter, + options.clock) + : NoRecordEventsSpanImpl.create( + SpanContext.create(traceId, spanId, traceOptions, tracestate)); linkSpans(span, parentLinks); return span; } @@ -186,7 +178,7 @@ final class SpanBuilderImpl extends SpanBuilder { } @Override - public SpanImpl startSpan() { + public Span startSpan() { SpanContext parentContext = remoteParentSpanContext; Boolean hasRemoteParent = Boolean.TRUE; TimestampConverter timestampConverter = null; @@ -199,8 +191,8 @@ final class SpanBuilderImpl extends SpanBuilder { parentContext = parent.getContext(); // Pass the timestamp converter from the parent to ensure that the recorded events are in // the right order. Implementation uses System.nanoTime() which is monotonically increasing. - if (parent instanceof SpanImpl) { - timestampConverter = ((SpanImpl) parent).getTimestampConverter(); + if (parent instanceof RecordEventsSpanImpl) { + timestampConverter = ((RecordEventsSpanImpl) parent).getTimestampConverter(); } } else { hasRemoteParent = null; @@ -219,13 +211,13 @@ final class SpanBuilderImpl extends SpanBuilder { static final class Options { private final RandomHandler randomHandler; - private final SpanImpl.StartEndHandler startEndHandler; + private final RecordEventsSpanImpl.StartEndHandler startEndHandler; private final Clock clock; private final TraceConfig traceConfig; Options( RandomHandler randomHandler, - SpanImpl.StartEndHandler startEndHandler, + RecordEventsSpanImpl.StartEndHandler startEndHandler, Clock clock, TraceConfig traceConfig) { this.randomHandler = checkNotNull(randomHandler, "randomHandler"); diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/SpanImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/SpanImpl.java deleted file mode 100644 index 75509a7f..00000000 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/SpanImpl.java +++ /dev/null @@ -1,619 +0,0 @@ -/* - * Copyright 2017, OpenCensus 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.opencensus.implcore.trace; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.EvictingQueue; -import io.opencensus.common.Clock; -import io.opencensus.implcore.internal.CheckerFrameworkUtils; -import io.opencensus.implcore.internal.TimestampConverter; -import io.opencensus.implcore.trace.internal.ConcurrentIntrusiveList.Element; -import io.opencensus.trace.Annotation; -import io.opencensus.trace.AttributeValue; -import io.opencensus.trace.EndSpanOptions; -import io.opencensus.trace.Link; -import io.opencensus.trace.Span; -import io.opencensus.trace.SpanContext; -import io.opencensus.trace.SpanId; -import io.opencensus.trace.Status; -import io.opencensus.trace.Tracer; -import io.opencensus.trace.config.TraceParams; -import io.opencensus.trace.export.SpanData; -import io.opencensus.trace.export.SpanData.TimedEvent; -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; -import javax.annotation.concurrent.ThreadSafe; - -// TODO(hailongwen): remove the usage of `NetworkEvent` in the future. -/** Implementation for the {@link Span} class. */ -@ThreadSafe -public final class SpanImpl extends Span implements Element { - private static final Logger logger = Logger.getLogger(Tracer.class.getName()); - - // The parent SpanId of this span. Null if this is a root span. - @Nullable private final SpanId parentSpanId; - // True if the parent is on a different process. - @Nullable private final Boolean hasRemoteParent; - // Active trace params when the Span was created. - private final TraceParams traceParams; - // Handler called when the span starts and ends. - private final StartEndHandler startEndHandler; - // The displayed name of the span. - private final String name; - // The kind of the span. - @Nullable private final Kind kind; - // The clock used to get the time. - private final Clock clock; - // The time converter used to convert nano time to Timestamp. This is needed because Java has - // millisecond granularity for Timestamp and tracing events are recorded more often. - @Nullable private final TimestampConverter timestampConverter; - // The start time of the span. Set when the span is created iff the RECORD_EVENTS options is - // set, otherwise 0. - private final long startNanoTime; - // Set of recorded attributes. DO NOT CALL any other method that changes the ordering of events. - @GuardedBy("this") - @Nullable - private AttributesWithCapacity attributes; - // List of recorded annotations. - @GuardedBy("this") - @Nullable - private TraceEvents> annotations; - // List of recorded network events. - @GuardedBy("this") - @Nullable - @SuppressWarnings("deprecation") - private TraceEvents> networkEvents; - // List of recorded links to parent and child spans. - @GuardedBy("this") - @Nullable - private TraceEvents links; - // The status of the span. Set when the span is ended iff the RECORD_EVENTS options is set. - @GuardedBy("this") - @Nullable - private Status status; - // The end time of the span. Set when the span is ended iff the RECORD_EVENTS options is set, - // otherwise 0. - @GuardedBy("this") - private long endNanoTime; - // True if the span is ended. - @GuardedBy("this") - private boolean hasBeenEnded; - - @GuardedBy("this") - private boolean sampleToLocalSpanStore; - - // Pointers for the ConcurrentIntrusiveList$Element. Guarded by the ConcurrentIntrusiveList. - @Nullable private SpanImpl next = null; - @Nullable private SpanImpl prev = null; - - /** - * Creates and starts a span with the given configuration. - * - * @param context supplies the trace_id and span_id for the newly started span. - * @param options the options for the new span, importantly Options.RECORD_EVENTS. - * @param name the displayed name for the new span. - * @param parentSpanId the span_id of the parent span, or null if the new span is a root span. - * @param hasRemoteParent {@code true} if the parentContext is remote. {@code null} if this is a - * root span. - * @param traceParams trace parameters like sampler and probability. - * @param startEndHandler handler called when the span starts and ends. - * @param timestampConverter null if the span is a root span or the parent is not sampled. If the - * parent is sampled, we should use the same converter to ensure ordering between tracing - * events. - * @param clock the clock used to get the time. - * @return a new and started span. - */ - @VisibleForTesting - public static SpanImpl startSpan( - SpanContext context, - @Nullable EnumSet options, - String name, - @Nullable Kind kind, - @Nullable SpanId parentSpanId, - @Nullable Boolean hasRemoteParent, - TraceParams traceParams, - StartEndHandler startEndHandler, - @Nullable TimestampConverter timestampConverter, - Clock clock) { - SpanImpl span = - new SpanImpl( - context, - options, - name, - kind, - parentSpanId, - hasRemoteParent, - traceParams, - startEndHandler, - timestampConverter, - clock); - // Call onStart here instead of calling in the constructor to make sure the span is completely - // initialized. - if (span.getOptions().contains(Options.RECORD_EVENTS)) { - startEndHandler.onStart(span); - } - return span; - } - - /** - * Returns the name of the {@code Span}. - * - * @return the name of the {@code Span}. - */ - public String getName() { - return name; - } - - /** - * Returns the status of the {@code Span}. If not set defaults to {@link Status#OK}. - * - * @return the status of the {@code Span}. - */ - public Status getStatus() { - synchronized (this) { - return getStatusWithDefault(); - } - } - - /** - * Returns the end nano time (see {@link System#nanoTime()}). If the current {@code Span} is not - * ended then returns {@link Clock#nowNanos()}. - * - * @return the end nano time. - */ - public long getEndNanoTime() { - synchronized (this) { - return hasBeenEnded ? endNanoTime : clock.nowNanos(); - } - } - - /** - * Returns the latency of the {@code Span} in nanos. If still active then returns now() - start - * time. - * - * @return the latency of the {@code Span} in nanos. - */ - public long getLatencyNs() { - synchronized (this) { - return hasBeenEnded ? endNanoTime - startNanoTime : clock.nowNanos() - startNanoTime; - } - } - - /** - * Returns if the name of this {@code Span} must be register to the {@code SampledSpanStore}. - * - * @return if the name of this {@code Span} must be register to the {@code SampledSpanStore}. - */ - public boolean getSampleToLocalSpanStore() { - synchronized (this) { - checkState(hasBeenEnded, "Running span does not have the SampleToLocalSpanStore set."); - return sampleToLocalSpanStore; - } - } - - /** - * Returns the kind of this {@code Span}. - * - * @return the kind of this {@code Span}. - */ - @Nullable - public Kind getKind() { - return kind; - } - - /** - * Returns the {@code TimestampConverter} used by this {@code Span}. - * - * @return the {@code TimestampConverter} used by this {@code Span}. - */ - @Nullable - TimestampConverter getTimestampConverter() { - return timestampConverter; - } - - /** - * Returns an immutable representation of all the data from this {@code Span}. - * - * @return an immutable representation of all the data from this {@code Span}. - * @throws IllegalStateException if the Span doesn't have RECORD_EVENTS option. - */ - public SpanData toSpanData() { - checkState( - getOptions().contains(Options.RECORD_EVENTS), - "Getting SpanData for a Span without RECORD_EVENTS option."); - synchronized (this) { - SpanData.Attributes attributesSpanData = - attributes == null - ? SpanData.Attributes.create(Collections.emptyMap(), 0) - : SpanData.Attributes.create(attributes, attributes.getNumberOfDroppedAttributes()); - SpanData.TimedEvents annotationsSpanData = - createTimedEvents(getInitializedAnnotations(), timestampConverter); - @SuppressWarnings("deprecation") - SpanData.TimedEvents networkEventsSpanData = - createTimedEvents(getInitializedNetworkEvents(), timestampConverter); - SpanData.Links linksSpanData = - links == null - ? SpanData.Links.create(Collections.emptyList(), 0) - : SpanData.Links.create( - new ArrayList(links.events), links.getNumberOfDroppedEvents()); - return SpanData.create( - getContext(), - parentSpanId, - hasRemoteParent, - name, - kind, - CheckerFrameworkUtils.castNonNull(timestampConverter).convertNanoTime(startNanoTime), - attributesSpanData, - annotationsSpanData, - networkEventsSpanData, - linksSpanData, - null, // Not supported yet. - hasBeenEnded ? getStatusWithDefault() : null, - hasBeenEnded - ? CheckerFrameworkUtils.castNonNull(timestampConverter).convertNanoTime(endNanoTime) - : null); - } - } - - @Override - public void putAttribute(String key, AttributeValue value) { - Preconditions.checkNotNull(key, "key"); - Preconditions.checkNotNull(value, "value"); - if (!getOptions().contains(Options.RECORD_EVENTS)) { - return; - } - synchronized (this) { - if (hasBeenEnded) { - logger.log(Level.FINE, "Calling putAttributes() on an ended Span."); - return; - } - getInitializedAttributes().putAttribute(key, value); - } - } - - @Override - public void putAttributes(Map attributes) { - Preconditions.checkNotNull(attributes, "attributes"); - if (!getOptions().contains(Options.RECORD_EVENTS)) { - return; - } - synchronized (this) { - if (hasBeenEnded) { - logger.log(Level.FINE, "Calling putAttributes() on an ended Span."); - return; - } - getInitializedAttributes().putAttributes(attributes); - } - } - - @Override - public void addAnnotation(String description, Map attributes) { - Preconditions.checkNotNull(description, "description"); - Preconditions.checkNotNull(attributes, "attribute"); - if (!getOptions().contains(Options.RECORD_EVENTS)) { - return; - } - synchronized (this) { - if (hasBeenEnded) { - logger.log(Level.FINE, "Calling addAnnotation() on an ended Span."); - return; - } - getInitializedAnnotations() - .addEvent( - new EventWithNanoTime( - clock.nowNanos(), - Annotation.fromDescriptionAndAttributes(description, attributes))); - } - } - - @Override - public void addAnnotation(Annotation annotation) { - Preconditions.checkNotNull(annotation, "annotation"); - if (!getOptions().contains(Options.RECORD_EVENTS)) { - return; - } - synchronized (this) { - if (hasBeenEnded) { - logger.log(Level.FINE, "Calling addAnnotation() on an ended Span."); - return; - } - getInitializedAnnotations() - .addEvent(new EventWithNanoTime(clock.nowNanos(), annotation)); - } - } - - @Override - @SuppressWarnings("deprecation") - public void addNetworkEvent(io.opencensus.trace.NetworkEvent networkEvent) { - if (!getOptions().contains(Options.RECORD_EVENTS)) { - return; - } - synchronized (this) { - if (hasBeenEnded) { - logger.log(Level.FINE, "Calling addNetworkEvent() on an ended Span."); - return; - } - getInitializedNetworkEvents() - .addEvent( - new EventWithNanoTime( - clock.nowNanos(), checkNotNull(networkEvent, "networkEvent"))); - } - } - - @Override - public void addLink(Link link) { - Preconditions.checkNotNull(link, "link"); - if (!getOptions().contains(Options.RECORD_EVENTS)) { - return; - } - synchronized (this) { - if (hasBeenEnded) { - logger.log(Level.FINE, "Calling addLink() on an ended Span."); - return; - } - getInitializedLinks().addEvent(link); - } - } - - @Override - public void setStatus(Status status) { - Preconditions.checkNotNull(status, "status"); - if (!getOptions().contains(Options.RECORD_EVENTS)) { - return; - } - synchronized (this) { - if (hasBeenEnded) { - logger.log(Level.FINE, "Calling setStatus() on an ended Span."); - return; - } - this.status = status; - } - } - - @Override - public void end(EndSpanOptions options) { - Preconditions.checkNotNull(options, "options"); - if (!getOptions().contains(Options.RECORD_EVENTS)) { - return; - } - synchronized (this) { - if (hasBeenEnded) { - logger.log(Level.FINE, "Calling end() on an ended Span."); - return; - } - if (options.getStatus() != null) { - status = options.getStatus(); - } - sampleToLocalSpanStore = options.getSampleToLocalSpanStore(); - endNanoTime = clock.nowNanos(); - hasBeenEnded = true; - } - startEndHandler.onEnd(this); - } - - @GuardedBy("this") - private AttributesWithCapacity getInitializedAttributes() { - if (attributes == null) { - attributes = new AttributesWithCapacity(traceParams.getMaxNumberOfAttributes()); - } - return attributes; - } - - @GuardedBy("this") - private TraceEvents> getInitializedAnnotations() { - if (annotations == null) { - annotations = - new TraceEvents>(traceParams.getMaxNumberOfAnnotations()); - } - return annotations; - } - - @GuardedBy("this") - @SuppressWarnings("deprecation") - private TraceEvents> - getInitializedNetworkEvents() { - if (networkEvents == null) { - networkEvents = - new TraceEvents>( - traceParams.getMaxNumberOfNetworkEvents()); - } - return networkEvents; - } - - @GuardedBy("this") - private TraceEvents getInitializedLinks() { - if (links == null) { - links = new TraceEvents(traceParams.getMaxNumberOfLinks()); - } - return links; - } - - @GuardedBy("this") - private Status getStatusWithDefault() { - return status == null ? Status.OK : status; - } - - private static SpanData.TimedEvents createTimedEvents( - TraceEvents> events, @Nullable TimestampConverter timestampConverter) { - if (events == null) { - return SpanData.TimedEvents.create(Collections.>emptyList(), 0); - } - List> eventsList = new ArrayList>(events.events.size()); - for (EventWithNanoTime networkEvent : events.events) { - eventsList.add( - networkEvent.toSpanDataTimedEvent(CheckerFrameworkUtils.castNonNull(timestampConverter))); - } - return SpanData.TimedEvents.create(eventsList, events.getNumberOfDroppedEvents()); - } - - @Override - @Nullable - public SpanImpl getNext() { - return next; - } - - @Override - public void setNext(@Nullable SpanImpl element) { - next = element; - } - - @Override - @Nullable - public SpanImpl getPrev() { - return prev; - } - - @Override - public void setPrev(@Nullable SpanImpl element) { - prev = element; - } - - /** - * Interface to handle the start and end operations for a {@link Span} only when the {@code Span} - * has {@link Options#RECORD_EVENTS} option. - * - *

Implementation must avoid high overhead work in any of the methods because the code is - * executed on the critical path. - * - *

One instance can be called by multiple threads in the same time, so the implementation must - * be thread-safe. - */ - public interface StartEndHandler { - void onStart(SpanImpl span); - - void onEnd(SpanImpl span); - } - - // A map implementation with a fixed capacity that drops events when the map gets full. Eviction - // is based on the access order. - private static final class AttributesWithCapacity extends LinkedHashMap { - private final int capacity; - private int totalRecordedAttributes = 0; - // Here because -Werror complains about this: [serial] serializable class AttributesWithCapacity - // has no definition of serialVersionUID. This class shouldn't be serialized. - private static final long serialVersionUID = 42L; - - private AttributesWithCapacity(int capacity) { - // Capacity of the map is capacity + 1 to avoid resizing because removeEldestEntry is invoked - // by put and putAll after inserting a new entry into the map. The loadFactor is set to 1 - // to avoid resizing because. The accessOrder is set to true. - super(capacity + 1, 1, /*accessOrder=*/ true); - this.capacity = capacity; - } - - // Users must call this method instead of put to keep count of the total number of entries - // inserted. - private void putAttribute(String key, AttributeValue value) { - totalRecordedAttributes += 1; - put(key, value); - } - - // Users must call this method instead of putAll to keep count of the total number of entries - // inserted. - private void putAttributes(Map attributes) { - totalRecordedAttributes += attributes.size(); - putAll(attributes); - } - - private int getNumberOfDroppedAttributes() { - return totalRecordedAttributes - size(); - } - - // It is called after each put or putAll call in order to determine if the eldest inserted - // entry should be removed or not. - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > this.capacity; - } - } - - private static final class TraceEvents { - private int totalRecordedEvents = 0; - private final EvictingQueue events; - - private int getNumberOfDroppedEvents() { - return totalRecordedEvents - events.size(); - } - - TraceEvents(int maxNumEvents) { - events = EvictingQueue.create(maxNumEvents); - } - - void addEvent(T event) { - totalRecordedEvents++; - events.add(event); - } - } - - // Timed event that uses nanoTime to represent the Timestamp. - private static final class EventWithNanoTime { - private final long nanoTime; - private final T event; - - private EventWithNanoTime(long nanoTime, T event) { - this.nanoTime = nanoTime; - this.event = event; - } - - private TimedEvent toSpanDataTimedEvent(TimestampConverter timestampConverter) { - return TimedEvent.create(timestampConverter.convertNanoTime(nanoTime), event); - } - } - - private SpanImpl( - SpanContext context, - @Nullable EnumSet options, - String name, - @Nullable Kind kind, - @Nullable SpanId parentSpanId, - @Nullable Boolean hasRemoteParent, - TraceParams traceParams, - StartEndHandler startEndHandler, - @Nullable TimestampConverter timestampConverter, - Clock clock) { - super(context, options); - this.parentSpanId = parentSpanId; - this.hasRemoteParent = hasRemoteParent; - this.name = name; - this.kind = kind; - this.traceParams = traceParams; - this.startEndHandler = startEndHandler; - this.clock = clock; - this.hasBeenEnded = false; - this.sampleToLocalSpanStore = false; - if (options != null && options.contains(Options.RECORD_EVENTS)) { - this.timestampConverter = - timestampConverter != null ? timestampConverter : TimestampConverter.now(clock); - startNanoTime = clock.nowNanos(); - } else { - this.startNanoTime = 0; - this.timestampConverter = timestampConverter; - } - } -} diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/StartEndHandlerImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/StartEndHandlerImpl.java index e22a86bd..6adaa200 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/StartEndHandlerImpl.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/StartEndHandlerImpl.java @@ -17,7 +17,7 @@ package io.opencensus.implcore.trace; import io.opencensus.implcore.internal.EventQueue; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; import io.opencensus.implcore.trace.export.RunningSpanStoreImpl; import io.opencensus.implcore.trace.export.SampledSpanStoreImpl; import io.opencensus.implcore.trace.export.SpanExporterImpl; @@ -61,14 +61,14 @@ public final class StartEndHandlerImpl implements StartEndHandler { } @Override - public void onStart(SpanImpl span) { + public void onStart(RecordEventsSpanImpl span) { if (span.getOptions().contains(Options.RECORD_EVENTS) && enqueueEventForNonSampledSpans) { eventQueue.enqueue(new SpanStartEvent(span, runningSpanStore)); } } @Override - public void onEnd(SpanImpl span) { + public void onEnd(RecordEventsSpanImpl span) { if ((span.getOptions().contains(Options.RECORD_EVENTS) && enqueueEventForNonSampledSpans) || span.getContext().getTraceOptions().isSampled()) { eventQueue.enqueue(new SpanEndEvent(span, spanExporter, runningSpanStore, sampledSpanStore)); @@ -77,10 +77,10 @@ public final class StartEndHandlerImpl implements StartEndHandler { // An EventQueue entry that records the start of the span event. private static final class SpanStartEvent implements EventQueue.Entry { - private final SpanImpl span; + private final RecordEventsSpanImpl span; @Nullable private final RunningSpanStoreImpl activeSpansExporter; - SpanStartEvent(SpanImpl span, @Nullable RunningSpanStoreImpl activeSpansExporter) { + SpanStartEvent(RecordEventsSpanImpl span, @Nullable RunningSpanStoreImpl activeSpansExporter) { this.span = span; this.activeSpansExporter = activeSpansExporter; } @@ -95,13 +95,13 @@ public final class StartEndHandlerImpl implements StartEndHandler { // An EventQueue entry that records the end of the span event. private static final class SpanEndEvent implements EventQueue.Entry { - private final SpanImpl span; + private final RecordEventsSpanImpl span; @Nullable private final RunningSpanStoreImpl runningSpanStore; private final SpanExporterImpl spanExporter; @Nullable private final SampledSpanStoreImpl sampledSpanStore; SpanEndEvent( - SpanImpl span, + RecordEventsSpanImpl span, SpanExporterImpl spanExporter, @Nullable RunningSpanStoreImpl runningSpanStore, @Nullable SampledSpanStoreImpl sampledSpanStore) { diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/TraceComponentImplBase.java b/impl_core/src/main/java/io/opencensus/implcore/trace/TraceComponentImplBase.java index f4c5ef76..c1432432 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/TraceComponentImplBase.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/TraceComponentImplBase.java @@ -19,7 +19,7 @@ package io.opencensus.implcore.trace; import io.opencensus.common.Clock; import io.opencensus.implcore.internal.EventQueue; import io.opencensus.implcore.internal.SimpleEventQueue; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; import io.opencensus.implcore.trace.config.TraceConfigImpl; import io.opencensus.implcore.trace.export.ExportComponentImpl; import io.opencensus.implcore.trace.internal.RandomHandler; diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/TracerImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/TracerImpl.java index fcf30ff0..48df8055 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/TracerImpl.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/TracerImpl.java @@ -29,9 +29,9 @@ import javax.annotation.Nullable; public final class TracerImpl extends Tracer { private final SpanBuilderImpl.Options spanBuilderOptions; - public TracerImpl( + TracerImpl( RandomHandler randomHandler, - SpanImpl.StartEndHandler startEndHandler, + RecordEventsSpanImpl.StartEndHandler startEndHandler, Clock clock, TraceConfig traceConfig) { spanBuilderOptions = diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/export/InProcessRunningSpanStoreImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/export/InProcessRunningSpanStoreImpl.java index 3d8fb9ae..f7aeac71 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/export/InProcessRunningSpanStoreImpl.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/export/InProcessRunningSpanStoreImpl.java @@ -16,7 +16,7 @@ package io.opencensus.implcore.trace.export; -import io.opencensus.implcore.trace.SpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; import io.opencensus.implcore.trace.internal.ConcurrentIntrusiveList; import io.opencensus.trace.export.RunningSpanStore; import io.opencensus.trace.export.SpanData; @@ -30,27 +30,27 @@ import javax.annotation.concurrent.ThreadSafe; /** In-process implementation of the {@link RunningSpanStore}. */ @ThreadSafe public final class InProcessRunningSpanStoreImpl extends RunningSpanStoreImpl { - private final ConcurrentIntrusiveList runningSpans; + private final ConcurrentIntrusiveList runningSpans; public InProcessRunningSpanStoreImpl() { - runningSpans = new ConcurrentIntrusiveList(); + runningSpans = new ConcurrentIntrusiveList(); } @Override - public void onStart(SpanImpl span) { + public void onStart(RecordEventsSpanImpl span) { runningSpans.addElement(span); } @Override - public void onEnd(SpanImpl span) { + public void onEnd(RecordEventsSpanImpl span) { runningSpans.removeElement(span); } @Override public Summary getSummary() { - Collection allRunningSpans = runningSpans.getAll(); + Collection allRunningSpans = runningSpans.getAll(); Map numSpansPerName = new HashMap(); - for (SpanImpl span : allRunningSpans) { + for (RecordEventsSpanImpl span : allRunningSpans) { Integer prevValue = numSpansPerName.get(span.getName()); numSpansPerName.put(span.getName(), prevValue != null ? prevValue + 1 : 1); } @@ -64,11 +64,11 @@ public final class InProcessRunningSpanStoreImpl extends RunningSpanStoreImpl { @Override public Collection getRunningSpans(Filter filter) { - Collection allRunningSpans = runningSpans.getAll(); + Collection allRunningSpans = runningSpans.getAll(); int maxSpansToReturn = filter.getMaxSpansToReturn() == 0 ? allRunningSpans.size() : filter.getMaxSpansToReturn(); List ret = new ArrayList(maxSpansToReturn); - for (SpanImpl span : allRunningSpans) { + for (RecordEventsSpanImpl span : allRunningSpans) { if (ret.size() == maxSpansToReturn) { break; } diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/export/InProcessSampledSpanStoreImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/export/InProcessSampledSpanStoreImpl.java index fe0132d8..0d8e493b 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/export/InProcessSampledSpanStoreImpl.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/export/InProcessSampledSpanStoreImpl.java @@ -18,7 +18,7 @@ package io.opencensus.implcore.trace.export; import com.google.common.collect.EvictingQueue; import io.opencensus.implcore.internal.EventQueue; -import io.opencensus.implcore.trace.SpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; import io.opencensus.trace.Status; import io.opencensus.trace.Status.CanonicalCode; import io.opencensus.trace.export.SampledSpanStore; @@ -59,8 +59,8 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { private static final class Bucket { - private final EvictingQueue sampledSpansQueue; - private final EvictingQueue notSampledSpansQueue; + private final EvictingQueue sampledSpansQueue; + private final EvictingQueue notSampledSpansQueue; private long lastSampledNanoTime; private long lastNotSampledNanoTime; @@ -69,7 +69,7 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { notSampledSpansQueue = EvictingQueue.create(numSamples); } - private void considerForSampling(SpanImpl span) { + private void considerForSampling(RecordEventsSpanImpl span) { long spanEndNanoTime = span.getEndNanoTime(); if (span.getContext().getTraceOptions().isSampled()) { // Need to compare by doing the subtraction all the time because in case of an overflow, @@ -90,14 +90,16 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { } } - private void getSamples(int maxSpansToReturn, List output) { + private void getSamples(int maxSpansToReturn, List output) { getSamples(maxSpansToReturn, output, sampledSpansQueue); getSamples(maxSpansToReturn, output, notSampledSpansQueue); } private static void getSamples( - int maxSpansToReturn, List output, EvictingQueue queue) { - for (SpanImpl span : queue) { + int maxSpansToReturn, + List output, + EvictingQueue queue) { + for (RecordEventsSpanImpl span : queue) { if (output.size() >= maxSpansToReturn) { break; } @@ -106,7 +108,10 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { } private void getSamplesFilteredByLatency( - long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn, List output) { + long latencyLowerNs, + long latencyUpperNs, + int maxSpansToReturn, + List output) { getSamplesFilteredByLatency( latencyLowerNs, latencyUpperNs, maxSpansToReturn, output, sampledSpansQueue); getSamplesFilteredByLatency( @@ -117,9 +122,9 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn, - List output, - EvictingQueue queue) { - for (SpanImpl span : queue) { + List output, + EvictingQueue queue) { + for (RecordEventsSpanImpl span : queue) { if (output.size() >= maxSpansToReturn) { break; } @@ -173,7 +178,7 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { return errorBuckets[code.value() - 1]; } - private void considerForSampling(SpanImpl span) { + private void considerForSampling(RecordEventsSpanImpl span) { Status status = span.getStatus(); // Null status means running Span, this should not happen in production, but the library // should not crash because of this. @@ -208,8 +213,10 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { return errorBucketSummaries; } - private List getErrorSamples(@Nullable CanonicalCode code, int maxSpansToReturn) { - ArrayList output = new ArrayList(maxSpansToReturn); + private List getErrorSamples( + @Nullable CanonicalCode code, int maxSpansToReturn) { + ArrayList output = + new ArrayList(maxSpansToReturn); if (code != null) { getErrorBucket(code).getSamples(maxSpansToReturn, output); } else { @@ -220,9 +227,10 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { return output; } - private List getLatencySamples( + private List getLatencySamples( long latencyLowerNs, long latencyUpperNs, int maxSpansToReturn) { - ArrayList output = new ArrayList(maxSpansToReturn); + ArrayList output = + new ArrayList(maxSpansToReturn); for (int i = 0; i < NUM_LATENCY_BUCKETS; i++) { LatencyBucketBoundaries boundaries = LatencyBucketBoundaries.values()[i]; if (latencyUpperNs >= boundaries.getLatencyLowerNs() @@ -257,7 +265,7 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { } @Override - public void considerForSampling(SpanImpl span) { + public void considerForSampling(RecordEventsSpanImpl span) { synchronized (samples) { String spanName = span.getName(); if (span.getSampleToLocalSpanStore() && !samples.containsKey(spanName)) { @@ -346,8 +354,9 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { filter.getMaxSpansToReturn() == 0 ? MAX_PER_SPAN_NAME_SAMPLES : filter.getMaxSpansToReturn(); - List spans = Collections.emptyList(); - // Try to not keep the lock to much, do the SpanImpl -> SpanData conversion outside the lock. + List spans = Collections.emptyList(); + // Try to not keep the lock to much, do the RecordEventsSpanImpl -> SpanData conversion outside + // the lock. synchronized (samples) { PerSpanNameSamples perSpanNameSamples = samples.get(filter.getSpanName()); if (perSpanNameSamples != null) { @@ -355,7 +364,7 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { } } List ret = new ArrayList(spans.size()); - for (SpanImpl span : spans) { + for (RecordEventsSpanImpl span : spans) { ret.add(span.toSpanData()); } return Collections.unmodifiableList(ret); @@ -367,8 +376,9 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { filter.getMaxSpansToReturn() == 0 ? MAX_PER_SPAN_NAME_SAMPLES : filter.getMaxSpansToReturn(); - List spans = Collections.emptyList(); - // Try to not keep the lock to much, do the SpanImpl -> SpanData conversion outside the lock. + List spans = Collections.emptyList(); + // Try to not keep the lock to much, do the RecordEventsSpanImpl -> SpanData conversion outside + // the lock. synchronized (samples) { PerSpanNameSamples perSpanNameSamples = samples.get(filter.getSpanName()); if (perSpanNameSamples != null) { @@ -378,7 +388,7 @@ public final class InProcessSampledSpanStoreImpl extends SampledSpanStoreImpl { } } List ret = new ArrayList(spans.size()); - for (SpanImpl span : spans) { + for (RecordEventsSpanImpl span : spans) { ret.add(span.toSpanData()); } return Collections.unmodifiableList(ret); diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/export/RunningSpanStoreImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/export/RunningSpanStoreImpl.java index 53147def..962f5b01 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/export/RunningSpanStoreImpl.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/export/RunningSpanStoreImpl.java @@ -16,11 +16,8 @@ package io.opencensus.implcore.trace.export; -import io.opencensus.implcore.trace.SpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; import io.opencensus.trace.export.RunningSpanStore; -import io.opencensus.trace.export.RunningSpanStore.Filter; -import io.opencensus.trace.export.RunningSpanStore.PerSpanNameSummary; -import io.opencensus.trace.export.RunningSpanStore.Summary; import io.opencensus.trace.export.SpanData; import java.util.Collection; import java.util.Collections; @@ -41,14 +38,14 @@ public abstract class RunningSpanStoreImpl extends RunningSpanStore { * * @param span the {@code Span} that started. */ - public abstract void onStart(SpanImpl span); + public abstract void onStart(RecordEventsSpanImpl span); /** * Removes the {@code Span} from the running spans list when the {@code Span} ends. * * @param span the {@code Span} that ended. */ - public abstract void onEnd(SpanImpl span); + public abstract void onEnd(RecordEventsSpanImpl span); private static final class NoopRunningSpanStoreImpl extends RunningSpanStoreImpl { @@ -56,10 +53,10 @@ public abstract class RunningSpanStoreImpl extends RunningSpanStore { RunningSpanStore.Summary.create(Collections.emptyMap()); @Override - public void onStart(SpanImpl span) {} + public void onStart(RecordEventsSpanImpl span) {} @Override - public void onEnd(SpanImpl span) {} + public void onEnd(RecordEventsSpanImpl span) {} @Override public Summary getSummary() { diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/export/SampledSpanStoreImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/export/SampledSpanStoreImpl.java index 302d5cd3..e67c2f8e 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/export/SampledSpanStoreImpl.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/export/SampledSpanStoreImpl.java @@ -16,12 +16,8 @@ package io.opencensus.implcore.trace.export; -import io.opencensus.implcore.trace.SpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; import io.opencensus.trace.export.SampledSpanStore; -import io.opencensus.trace.export.SampledSpanStore.ErrorFilter; -import io.opencensus.trace.export.SampledSpanStore.LatencyFilter; -import io.opencensus.trace.export.SampledSpanStore.PerSpanNameSummary; -import io.opencensus.trace.export.SampledSpanStore.Summary; import io.opencensus.trace.export.SpanData; import java.util.Collection; import java.util.Collections; @@ -43,7 +39,7 @@ public abstract class SampledSpanStoreImpl extends SampledSpanStore { * * @param span the span to be consider for storing into the store buckets. */ - public abstract void considerForSampling(SpanImpl span); + public abstract void considerForSampling(RecordEventsSpanImpl span); protected void shutdown() {} @@ -59,7 +55,7 @@ public abstract class SampledSpanStoreImpl extends SampledSpanStore { } @Override - public void considerForSampling(SpanImpl span) {} + public void considerForSampling(RecordEventsSpanImpl span) {} @Override public void registerSpanNamesForCollection(Collection spanNames) {} diff --git a/impl_core/src/main/java/io/opencensus/implcore/trace/export/SpanExporterImpl.java b/impl_core/src/main/java/io/opencensus/implcore/trace/export/SpanExporterImpl.java index b9b1e98c..51a7b05c 100644 --- a/impl_core/src/main/java/io/opencensus/implcore/trace/export/SpanExporterImpl.java +++ b/impl_core/src/main/java/io/opencensus/implcore/trace/export/SpanExporterImpl.java @@ -19,7 +19,7 @@ package io.opencensus.implcore.trace.export; import com.google.common.annotations.VisibleForTesting; import io.opencensus.common.Duration; import io.opencensus.implcore.internal.DaemonThreadFactory; -import io.opencensus.implcore.trace.SpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; import io.opencensus.trace.export.ExportComponent; import io.opencensus.trace.export.SpanData; import io.opencensus.trace.export.SpanExporter; @@ -60,7 +60,7 @@ public final class SpanExporterImpl extends SpanExporter { * * @param span the {@code Span} to be added. */ - public void addSpan(SpanImpl span) { + public void addSpan(RecordEventsSpanImpl span) { worker.addSpan(span); } @@ -108,14 +108,14 @@ public final class SpanExporterImpl extends SpanExporter { private final Object monitor = new Object(); @GuardedBy("monitor") - private final List spans; + private final List spans; private final Map serviceHandlers = new ConcurrentHashMap(); private final int bufferSize; private final long scheduleDelayMillis; // See SpanExporterImpl#addSpan. - private void addSpan(SpanImpl span) { + private void addSpan(RecordEventsSpanImpl span) { synchronized (monitor) { this.spans.add(span); if (spans.size() > bufferSize) { @@ -152,16 +152,16 @@ public final class SpanExporterImpl extends SpanExporter { } private Worker(int bufferSize, Duration scheduleDelay) { - spans = new ArrayList(bufferSize); + spans = new ArrayList(bufferSize); this.bufferSize = bufferSize; this.scheduleDelayMillis = scheduleDelay.toMillis(); } // Returns an unmodifiable list of all buffered spans data to ensure that any registered // service handler cannot modify the list. - private static List fromSpanImplToSpanData(List spans) { + private static List fromSpanImplToSpanData(List spans) { List spanDatas = new ArrayList(spans.size()); - for (SpanImpl span : spans) { + for (RecordEventsSpanImpl span : spans) { spanDatas.add(span.toSpanData()); } return Collections.unmodifiableList(spanDatas); @@ -172,7 +172,7 @@ public final class SpanExporterImpl extends SpanExporter { while (true) { // Copy all the batched spans in a separate list to release the monitor lock asap to // avoid blocking the producer thread. - List spansCopy; + List spansCopy; synchronized (monitor) { if (spans.size() < bufferSize) { do { @@ -187,7 +187,7 @@ public final class SpanExporterImpl extends SpanExporter { } } while (spans.isEmpty()); } - spansCopy = new ArrayList(spans); + spansCopy = new ArrayList(spans); spans.clear(); } // Execute the batch export outside the synchronized to not block all producers. @@ -199,9 +199,9 @@ public final class SpanExporterImpl extends SpanExporter { } void flush() { - List spansCopy; + List spansCopy; synchronized (monitor) { - spansCopy = new ArrayList(spans); + spansCopy = new ArrayList(spans); spans.clear(); } diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/NoRecordEventsSpanImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/NoRecordEventsSpanImplTest.java new file mode 100644 index 00000000..c576860d --- /dev/null +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/NoRecordEventsSpanImplTest.java @@ -0,0 +1,91 @@ +/* + * Copyright 2018, OpenCensus 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.opencensus.implcore.trace; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.trace.Annotation; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.EndSpanOptions; +import io.opencensus.trace.Link; +import io.opencensus.trace.MessageEvent; +import io.opencensus.trace.NetworkEvent; +import io.opencensus.trace.Span.Options; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.Status; +import io.opencensus.trace.TraceId; +import io.opencensus.trace.TraceOptions; +import io.opencensus.trace.Tracestate; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link NoRecordEventsSpanImpl}. */ +@RunWith(JUnit4.class) +public class NoRecordEventsSpanImplTest { + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), + SpanId.generateRandomId(random), + TraceOptions.DEFAULT, + Tracestate.builder().build()); + private final NoRecordEventsSpanImpl noRecordEventsSpan = + NoRecordEventsSpanImpl.create(spanContext); + + @Test + public void propagatesSpanContext() { + assertThat(noRecordEventsSpan.getContext()).isEqualTo(spanContext); + } + + @Test + public void hasNoRecordEventsOption() { + assertThat(noRecordEventsSpan.getOptions()).doesNotContain(Options.RECORD_EVENTS); + } + + @Test + public void doNotCrash() { + Map attributes = new HashMap(); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + Map multipleAttributes = new HashMap(); + multipleAttributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + multipleAttributes.put("MyBooleanAttributeKey", AttributeValue.booleanAttributeValue(true)); + multipleAttributes.put("MyLongAttributeKey", AttributeValue.longAttributeValue(123)); + // Tests only that all the methods are not crashing/throwing errors. + noRecordEventsSpan.putAttribute( + "MyStringAttributeKey2", AttributeValue.stringAttributeValue("MyStringAttributeValue2")); + noRecordEventsSpan.addAttributes(attributes); + noRecordEventsSpan.addAttributes(multipleAttributes); + noRecordEventsSpan.addAnnotation("MyAnnotation"); + noRecordEventsSpan.addAnnotation("MyAnnotation", attributes); + noRecordEventsSpan.addAnnotation("MyAnnotation", multipleAttributes); + noRecordEventsSpan.addAnnotation(Annotation.fromDescription("MyAnnotation")); + noRecordEventsSpan.addNetworkEvent(NetworkEvent.builder(NetworkEvent.Type.SENT, 1L).build()); + noRecordEventsSpan.addMessageEvent(MessageEvent.builder(MessageEvent.Type.SENT, 1L).build()); + noRecordEventsSpan.addLink( + Link.fromSpanContext(SpanContext.INVALID, Link.Type.CHILD_LINKED_SPAN)); + noRecordEventsSpan.setStatus(Status.OK); + noRecordEventsSpan.end(EndSpanOptions.DEFAULT); + noRecordEventsSpan.end(); + } +} diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/RecordEventsSpanImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/RecordEventsSpanImplTest.java new file mode 100644 index 00000000..b293a225 --- /dev/null +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/RecordEventsSpanImplTest.java @@ -0,0 +1,594 @@ +/* + * Copyright 2017, OpenCensus 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.opencensus.implcore.trace; + +import static com.google.common.truth.Truth.assertThat; + +import io.opencensus.common.Duration; +import io.opencensus.common.Timestamp; +import io.opencensus.implcore.internal.TimestampConverter; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; +import io.opencensus.testing.common.TestClock; +import io.opencensus.trace.Annotation; +import io.opencensus.trace.AttributeValue; +import io.opencensus.trace.EndSpanOptions; +import io.opencensus.trace.Link; +import io.opencensus.trace.NetworkEvent; +import io.opencensus.trace.Span.Kind; +import io.opencensus.trace.SpanContext; +import io.opencensus.trace.SpanId; +import io.opencensus.trace.Status; +import io.opencensus.trace.TraceId; +import io.opencensus.trace.TraceOptions; +import io.opencensus.trace.config.TraceParams; +import io.opencensus.trace.export.SpanData; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +/** Unit tests for {@link RecordEventsSpanImpl}. */ +@RunWith(JUnit4.class) +public class RecordEventsSpanImplTest { + private static final String SPAN_NAME = "MySpanName"; + private static final String ANNOTATION_DESCRIPTION = "MyAnnotation"; + private final Random random = new Random(1234); + private final SpanContext spanContext = + SpanContext.create( + TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); + private final SpanId parentSpanId = SpanId.generateRandomId(random); + private final Timestamp timestamp = Timestamp.create(1234, 5678); + private final TestClock testClock = TestClock.create(timestamp); + private final TimestampConverter timestampConverter = TimestampConverter.now(testClock); + private final Map attributes = new HashMap(); + private final Map expectedAttributes = + new HashMap(); + @Mock private StartEndHandler startEndHandler; + @Rule public final ExpectedException exception = ExpectedException.none(); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + attributes.put( + "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); + attributes.put("MyLongAttributeKey", AttributeValue.longAttributeValue(123L)); + attributes.put("MyBooleanAttributeKey", AttributeValue.booleanAttributeValue(false)); + expectedAttributes.putAll(attributes); + expectedAttributes.put( + "MySingleStringAttributeKey", + AttributeValue.stringAttributeValue("MySingleStringAttributeValue")); + } + + @Test + public void noEventsRecordedAfterEnd() { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + span.end(); + // Check that adding trace events after Span#end() does not throw any exception and are not + // recorded. + span.putAttributes(attributes); + span.putAttribute( + "MySingleStringAttributeKey", + AttributeValue.stringAttributeValue("MySingleStringAttributeValue")); + span.addAnnotation(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); + span.addAnnotation(ANNOTATION_DESCRIPTION, attributes); + span.addNetworkEvent( + NetworkEvent.builder(NetworkEvent.Type.RECV, 1).setUncompressedMessageSize(3).build()); + span.addLink(Link.fromSpanContext(spanContext, Link.Type.CHILD_LINKED_SPAN)); + SpanData spanData = span.toSpanData(); + assertThat(spanData.getStartTimestamp()).isEqualTo(timestamp); + assertThat(spanData.getAttributes().getAttributeMap()).isEmpty(); + assertThat(spanData.getAnnotations().getEvents()).isEmpty(); + assertThat(spanData.getNetworkEvents().getEvents()).isEmpty(); + assertThat(spanData.getLinks().getLinks()).isEmpty(); + assertThat(spanData.getStatus()).isEqualTo(Status.OK); + assertThat(spanData.getEndTimestamp()).isEqualTo(timestamp); + } + + @Test + public void deprecatedAddAttributesStillWorks() { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + span.addAttributes(attributes); + span.end(); + SpanData spanData = span.toSpanData(); + assertThat(spanData.getAttributes().getAttributeMap()).isEqualTo(attributes); + } + + @Test + public void toSpanData_ActiveSpan() { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + true, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + Mockito.verify(startEndHandler, Mockito.times(1)).onStart(span); + span.putAttribute( + "MySingleStringAttributeKey", + AttributeValue.stringAttributeValue("MySingleStringAttributeValue")); + span.putAttributes(attributes); + testClock.advanceTime(Duration.create(0, 100)); + span.addAnnotation(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); + testClock.advanceTime(Duration.create(0, 100)); + span.addAnnotation(ANNOTATION_DESCRIPTION, attributes); + testClock.advanceTime(Duration.create(0, 100)); + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1).setUncompressedMessageSize(3).build(); + span.addNetworkEvent(networkEvent); + testClock.advanceTime(Duration.create(0, 100)); + Link link = Link.fromSpanContext(spanContext, Link.Type.CHILD_LINKED_SPAN); + span.addLink(link); + SpanData spanData = span.toSpanData(); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isTrue(); + assertThat(spanData.getAttributes().getDroppedAttributesCount()).isEqualTo(0); + assertThat(spanData.getAttributes().getAttributeMap()).isEqualTo(expectedAttributes); + assertThat(spanData.getAnnotations().getDroppedEventsCount()).isEqualTo(0); + assertThat(spanData.getAnnotations().getEvents().size()).isEqualTo(2); + assertThat(spanData.getAnnotations().getEvents().get(0).getTimestamp()) + .isEqualTo(timestamp.addNanos(100)); + assertThat(spanData.getAnnotations().getEvents().get(0).getEvent()) + .isEqualTo(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); + assertThat(spanData.getAnnotations().getEvents().get(1).getTimestamp()) + .isEqualTo(timestamp.addNanos(200)); + assertThat(spanData.getAnnotations().getEvents().get(1).getEvent()) + .isEqualTo(Annotation.fromDescriptionAndAttributes(ANNOTATION_DESCRIPTION, attributes)); + assertThat(spanData.getNetworkEvents().getDroppedEventsCount()).isEqualTo(0); + assertThat(spanData.getNetworkEvents().getEvents().size()).isEqualTo(1); + assertThat(spanData.getNetworkEvents().getEvents().get(0).getTimestamp()) + .isEqualTo(timestamp.addNanos(300)); + assertThat(spanData.getNetworkEvents().getEvents().get(0).getEvent()).isEqualTo(networkEvent); + assertThat(spanData.getLinks().getDroppedLinksCount()).isEqualTo(0); + assertThat(spanData.getLinks().getLinks().size()).isEqualTo(1); + assertThat(spanData.getLinks().getLinks().get(0)).isEqualTo(link); + assertThat(spanData.getStartTimestamp()).isEqualTo(timestamp); + assertThat(spanData.getStatus()).isNull(); + assertThat(spanData.getEndTimestamp()).isNull(); + } + + @Test + public void toSpanData_EndedSpan() { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + Mockito.verify(startEndHandler, Mockito.times(1)).onStart(span); + span.putAttribute( + "MySingleStringAttributeKey", + AttributeValue.stringAttributeValue("MySingleStringAttributeValue")); + span.putAttributes(attributes); + testClock.advanceTime(Duration.create(0, 100)); + span.addAnnotation(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); + testClock.advanceTime(Duration.create(0, 100)); + span.addAnnotation(ANNOTATION_DESCRIPTION, attributes); + testClock.advanceTime(Duration.create(0, 100)); + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1).setUncompressedMessageSize(3).build(); + span.addNetworkEvent(networkEvent); + Link link = Link.fromSpanContext(spanContext, Link.Type.CHILD_LINKED_SPAN); + span.addLink(link); + testClock.advanceTime(Duration.create(0, 100)); + span.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); + Mockito.verify(startEndHandler, Mockito.times(1)).onEnd(span); + SpanData spanData = span.toSpanData(); + assertThat(spanData.getContext()).isEqualTo(spanContext); + assertThat(spanData.getName()).isEqualTo(SPAN_NAME); + assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); + assertThat(spanData.getHasRemoteParent()).isFalse(); + assertThat(spanData.getAttributes().getDroppedAttributesCount()).isEqualTo(0); + assertThat(spanData.getAttributes().getAttributeMap()).isEqualTo(expectedAttributes); + assertThat(spanData.getAnnotations().getDroppedEventsCount()).isEqualTo(0); + assertThat(spanData.getAnnotations().getEvents().size()).isEqualTo(2); + assertThat(spanData.getAnnotations().getEvents().get(0).getTimestamp()) + .isEqualTo(timestamp.addNanos(100)); + assertThat(spanData.getAnnotations().getEvents().get(0).getEvent()) + .isEqualTo(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); + assertThat(spanData.getAnnotations().getEvents().get(1).getTimestamp()) + .isEqualTo(timestamp.addNanos(200)); + assertThat(spanData.getAnnotations().getEvents().get(1).getEvent()) + .isEqualTo(Annotation.fromDescriptionAndAttributes(ANNOTATION_DESCRIPTION, attributes)); + assertThat(spanData.getNetworkEvents().getDroppedEventsCount()).isEqualTo(0); + assertThat(spanData.getNetworkEvents().getEvents().size()).isEqualTo(1); + assertThat(spanData.getNetworkEvents().getEvents().get(0).getTimestamp()) + .isEqualTo(timestamp.addNanos(300)); + assertThat(spanData.getNetworkEvents().getEvents().get(0).getEvent()).isEqualTo(networkEvent); + assertThat(spanData.getLinks().getDroppedLinksCount()).isEqualTo(0); + assertThat(spanData.getLinks().getLinks().size()).isEqualTo(1); + assertThat(spanData.getLinks().getLinks().get(0)).isEqualTo(link); + assertThat(spanData.getStartTimestamp()).isEqualTo(timestamp); + assertThat(spanData.getStatus()).isEqualTo(Status.CANCELLED); + assertThat(spanData.getEndTimestamp()).isEqualTo(timestamp.addNanos(400)); + } + + @Test + public void status_ViaSetStatus() { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + Mockito.verify(startEndHandler, Mockito.times(1)).onStart(span); + testClock.advanceTime(Duration.create(0, 100)); + assertThat(span.getStatus()).isEqualTo(Status.OK); + span.setStatus(Status.CANCELLED); + assertThat(span.getStatus()).isEqualTo(Status.CANCELLED); + span.end(); + assertThat(span.getStatus()).isEqualTo(Status.CANCELLED); + } + + @Test + public void status_ViaEndSpanOptions() { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + Mockito.verify(startEndHandler, Mockito.times(1)).onStart(span); + testClock.advanceTime(Duration.create(0, 100)); + assertThat(span.getStatus()).isEqualTo(Status.OK); + span.setStatus(Status.CANCELLED); + assertThat(span.getStatus()).isEqualTo(Status.CANCELLED); + span.end(EndSpanOptions.builder().setStatus(Status.ABORTED).build()); + assertThat(span.getStatus()).isEqualTo(Status.ABORTED); + } + + @Test + public void droppingAttributes() { + final int maxNumberOfAttributes = 8; + TraceParams traceParams = + TraceParams.DEFAULT.toBuilder().setMaxNumberOfAttributes(maxNumberOfAttributes).build(); + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + traceParams, + startEndHandler, + timestampConverter, + testClock); + for (int i = 0; i < 2 * maxNumberOfAttributes; i++) { + Map attributes = new HashMap(); + attributes.put("MyStringAttributeKey" + i, AttributeValue.longAttributeValue(i)); + span.putAttributes(attributes); + } + SpanData spanData = span.toSpanData(); + assertThat(spanData.getAttributes().getDroppedAttributesCount()) + .isEqualTo(maxNumberOfAttributes); + assertThat(spanData.getAttributes().getAttributeMap().size()).isEqualTo(maxNumberOfAttributes); + for (int i = 0; i < maxNumberOfAttributes; i++) { + assertThat( + spanData + .getAttributes() + .getAttributeMap() + .get("MyStringAttributeKey" + (i + maxNumberOfAttributes))) + .isEqualTo(AttributeValue.longAttributeValue(i + maxNumberOfAttributes)); + } + span.end(); + spanData = span.toSpanData(); + assertThat(spanData.getAttributes().getDroppedAttributesCount()) + .isEqualTo(maxNumberOfAttributes); + assertThat(spanData.getAttributes().getAttributeMap().size()).isEqualTo(maxNumberOfAttributes); + for (int i = 0; i < maxNumberOfAttributes; i++) { + assertThat( + spanData + .getAttributes() + .getAttributeMap() + .get("MyStringAttributeKey" + (i + maxNumberOfAttributes))) + .isEqualTo(AttributeValue.longAttributeValue(i + maxNumberOfAttributes)); + } + } + + @Test + public void droppingAndAddingAttributes() { + final int maxNumberOfAttributes = 8; + TraceParams traceParams = + TraceParams.DEFAULT.toBuilder().setMaxNumberOfAttributes(maxNumberOfAttributes).build(); + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + traceParams, + startEndHandler, + timestampConverter, + testClock); + for (int i = 0; i < 2 * maxNumberOfAttributes; i++) { + Map attributes = new HashMap(); + attributes.put("MyStringAttributeKey" + i, AttributeValue.longAttributeValue(i)); + span.putAttributes(attributes); + } + SpanData spanData = span.toSpanData(); + assertThat(spanData.getAttributes().getDroppedAttributesCount()) + .isEqualTo(maxNumberOfAttributes); + assertThat(spanData.getAttributes().getAttributeMap().size()).isEqualTo(maxNumberOfAttributes); + for (int i = 0; i < maxNumberOfAttributes; i++) { + assertThat( + spanData + .getAttributes() + .getAttributeMap() + .get("MyStringAttributeKey" + (i + maxNumberOfAttributes))) + .isEqualTo(AttributeValue.longAttributeValue(i + maxNumberOfAttributes)); + } + for (int i = 0; i < maxNumberOfAttributes / 2; i++) { + Map attributes = new HashMap(); + attributes.put("MyStringAttributeKey" + i, AttributeValue.longAttributeValue(i)); + span.putAttributes(attributes); + } + spanData = span.toSpanData(); + assertThat(spanData.getAttributes().getDroppedAttributesCount()) + .isEqualTo(maxNumberOfAttributes * 3 / 2); + assertThat(spanData.getAttributes().getAttributeMap().size()).isEqualTo(maxNumberOfAttributes); + // Test that we still have in the attributes map the latest maxNumberOfAttributes / 2 entries. + for (int i = 0; i < maxNumberOfAttributes / 2; i++) { + assertThat( + spanData + .getAttributes() + .getAttributeMap() + .get("MyStringAttributeKey" + (i + maxNumberOfAttributes * 3 / 2))) + .isEqualTo(AttributeValue.longAttributeValue(i + maxNumberOfAttributes * 3 / 2)); + } + // Test that we have the newest re-added initial entries. + for (int i = 0; i < maxNumberOfAttributes / 2; i++) { + assertThat(spanData.getAttributes().getAttributeMap().get("MyStringAttributeKey" + i)) + .isEqualTo(AttributeValue.longAttributeValue(i)); + } + } + + @Test + public void droppingAnnotations() { + final int maxNumberOfAnnotations = 8; + TraceParams traceParams = + TraceParams.DEFAULT.toBuilder().setMaxNumberOfAnnotations(maxNumberOfAnnotations).build(); + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + traceParams, + startEndHandler, + timestampConverter, + testClock); + Annotation annotation = Annotation.fromDescription(ANNOTATION_DESCRIPTION); + for (int i = 0; i < 2 * maxNumberOfAnnotations; i++) { + span.addAnnotation(annotation); + testClock.advanceTime(Duration.create(0, 100)); + } + SpanData spanData = span.toSpanData(); + assertThat(spanData.getAnnotations().getDroppedEventsCount()).isEqualTo(maxNumberOfAnnotations); + assertThat(spanData.getAnnotations().getEvents().size()).isEqualTo(maxNumberOfAnnotations); + for (int i = 0; i < maxNumberOfAnnotations; i++) { + assertThat(spanData.getAnnotations().getEvents().get(i).getTimestamp()) + .isEqualTo(timestamp.addNanos(100L * (maxNumberOfAnnotations + i))); + assertThat(spanData.getAnnotations().getEvents().get(i).getEvent()).isEqualTo(annotation); + } + span.end(); + spanData = span.toSpanData(); + assertThat(spanData.getAnnotations().getDroppedEventsCount()).isEqualTo(maxNumberOfAnnotations); + assertThat(spanData.getAnnotations().getEvents().size()).isEqualTo(maxNumberOfAnnotations); + for (int i = 0; i < maxNumberOfAnnotations; i++) { + assertThat(spanData.getAnnotations().getEvents().get(i).getTimestamp()) + .isEqualTo(timestamp.addNanos(100L * (maxNumberOfAnnotations + i))); + assertThat(spanData.getAnnotations().getEvents().get(i).getEvent()).isEqualTo(annotation); + } + } + + @Test + public void droppingNetworkEvents() { + final int maxNumberOfNetworkEvents = 8; + TraceParams traceParams = + TraceParams.DEFAULT + .toBuilder() + .setMaxNumberOfNetworkEvents(maxNumberOfNetworkEvents) + .build(); + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + traceParams, + startEndHandler, + timestampConverter, + testClock); + NetworkEvent networkEvent = + NetworkEvent.builder(NetworkEvent.Type.RECV, 1).setUncompressedMessageSize(3).build(); + for (int i = 0; i < 2 * maxNumberOfNetworkEvents; i++) { + span.addNetworkEvent(networkEvent); + testClock.advanceTime(Duration.create(0, 100)); + } + SpanData spanData = span.toSpanData(); + assertThat(spanData.getNetworkEvents().getDroppedEventsCount()) + .isEqualTo(maxNumberOfNetworkEvents); + assertThat(spanData.getNetworkEvents().getEvents().size()).isEqualTo(maxNumberOfNetworkEvents); + for (int i = 0; i < maxNumberOfNetworkEvents; i++) { + assertThat(spanData.getNetworkEvents().getEvents().get(i).getTimestamp()) + .isEqualTo(timestamp.addNanos(100L * (maxNumberOfNetworkEvents + i))); + assertThat(spanData.getNetworkEvents().getEvents().get(i).getEvent()).isEqualTo(networkEvent); + } + span.end(); + spanData = span.toSpanData(); + assertThat(spanData.getNetworkEvents().getDroppedEventsCount()) + .isEqualTo(maxNumberOfNetworkEvents); + assertThat(spanData.getNetworkEvents().getEvents().size()).isEqualTo(maxNumberOfNetworkEvents); + for (int i = 0; i < maxNumberOfNetworkEvents; i++) { + assertThat(spanData.getNetworkEvents().getEvents().get(i).getTimestamp()) + .isEqualTo(timestamp.addNanos(100L * (maxNumberOfNetworkEvents + i))); + assertThat(spanData.getNetworkEvents().getEvents().get(i).getEvent()).isEqualTo(networkEvent); + } + } + + @Test + public void droppingLinks() { + final int maxNumberOfLinks = 8; + TraceParams traceParams = + TraceParams.DEFAULT.toBuilder().setMaxNumberOfLinks(maxNumberOfLinks).build(); + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + traceParams, + startEndHandler, + timestampConverter, + testClock); + Link link = Link.fromSpanContext(spanContext, Link.Type.CHILD_LINKED_SPAN); + for (int i = 0; i < 2 * maxNumberOfLinks; i++) { + span.addLink(link); + } + SpanData spanData = span.toSpanData(); + assertThat(spanData.getLinks().getDroppedLinksCount()).isEqualTo(maxNumberOfLinks); + assertThat(spanData.getLinks().getLinks().size()).isEqualTo(maxNumberOfLinks); + for (int i = 0; i < maxNumberOfLinks; i++) { + assertThat(spanData.getLinks().getLinks().get(i)).isEqualTo(link); + } + span.end(); + spanData = span.toSpanData(); + assertThat(spanData.getLinks().getDroppedLinksCount()).isEqualTo(maxNumberOfLinks); + assertThat(spanData.getLinks().getLinks().size()).isEqualTo(maxNumberOfLinks); + for (int i = 0; i < maxNumberOfLinks; i++) { + assertThat(spanData.getLinks().getLinks().get(i)).isEqualTo(link); + } + } + + @Test + public void sampleToLocalSpanStore() { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + span.end(EndSpanOptions.builder().setSampleToLocalSpanStore(true).build()); + Mockito.verify(startEndHandler, Mockito.times(1)).onEnd(span); + assertThat(span.getSampleToLocalSpanStore()).isTrue(); + span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + span.end(); + Mockito.verify(startEndHandler, Mockito.times(1)).onEnd(span); + assertThat(span.getSampleToLocalSpanStore()).isFalse(); + } + + @Test + public void sampleToLocalSpanStore_RunningSpan() { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + null, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + exception.expect(IllegalStateException.class); + exception.expectMessage("Running span does not have the SampleToLocalSpanStore set."); + span.getSampleToLocalSpanStore(); + } + + @Test + public void getSpanKind() { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( + spanContext, + SPAN_NAME, + Kind.SERVER, + parentSpanId, + false, + TraceParams.DEFAULT, + startEndHandler, + timestampConverter, + testClock); + assertThat(span.getKind()).isEqualTo(Kind.SERVER); + } +} diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java index 1804130c..3267eac5 100644 --- a/impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/SpanBuilderImplTest.java @@ -19,7 +19,7 @@ package io.opencensus.implcore.trace; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.when; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; import io.opencensus.implcore.trace.internal.RandomHandler; import io.opencensus.testing.common.TestClock; import io.opencensus.trace.Span; @@ -62,28 +62,56 @@ public class SpanBuilderImplTest { when(traceConfig.getActiveTraceParams()).thenReturn(alwaysSampleTraceParams); } + @Test + public void startSpan_CreatesTheCorrectSpanImplInstance() { + assertThat( + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.alwaysSample()) + .startSpan()) + .isInstanceOf(RecordEventsSpanImpl.class); + assertThat( + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setRecordEvents(true) + .setSampler(Samplers.neverSample()) + .startSpan()) + .isInstanceOf(RecordEventsSpanImpl.class); + assertThat( + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .startSpan()) + .isInstanceOf(NoRecordEventsSpanImpl.class); + } + @Test public void setSpanKind_NotNull() { - SpanImpl span = - SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) - .setSpanKind(Kind.CLIENT) - .startSpan(); + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSpanKind(Kind.CLIENT) + .setRecordEvents(true) + .startSpan(); assertThat(span.getKind()).isEqualTo(Kind.CLIENT); assertThat(span.toSpanData().getKind()).isEqualTo(Kind.CLIENT); } @Test public void setSpanKind_DefaultNull() { - SpanImpl span = - SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions).startSpan(); + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setRecordEvents(true) + .startSpan(); assertThat(span.getKind()).isNull(); assertThat(span.toSpanData().getKind()).isNull(); } @Test public void startSpanNullParent() { - SpanImpl span = - SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions).startSpan(); + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setRecordEvents(true) + .startSpan(); assertThat(span.getContext().isValid()).isTrue(); assertThat(span.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); assertThat(span.getContext().getTraceOptions().isSampled()).isTrue(); @@ -96,11 +124,12 @@ public class SpanBuilderImplTest { @Test public void startSpanNullParentWithRecordEvents() { - SpanImpl span = - SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) - .setSampler(Samplers.neverSample()) - .setRecordEvents(true) - .startSpan(); + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithParent(SPAN_NAME, null, spanBuilderOptions) + .setSampler(Samplers.neverSample()) + .setRecordEvents(true) + .startSpan(); assertThat(span.getContext().isValid()).isTrue(); assertThat(span.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); assertThat(span.getContext().getTraceOptions().isSampled()).isFalse(); @@ -127,22 +156,25 @@ public class SpanBuilderImplTest { assertThat(rootSpan.getContext().isValid()).isTrue(); assertThat(rootSpan.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); assertThat(rootSpan.getContext().getTraceOptions().isSampled()).isTrue(); - assertThat(((SpanImpl) rootSpan).toSpanData().getHasRemoteParent()).isNull(); + assertThat(((RecordEventsSpanImpl) rootSpan).toSpanData().getHasRemoteParent()).isNull(); Span childSpan = SpanBuilderImpl.createWithParent(SPAN_NAME, rootSpan, spanBuilderOptions).startSpan(); assertThat(childSpan.getContext().isValid()).isTrue(); assertThat(childSpan.getContext().getTraceId()).isEqualTo(rootSpan.getContext().getTraceId()); - assertThat(((SpanImpl) childSpan).toSpanData().getParentSpanId()) + assertThat(((RecordEventsSpanImpl) childSpan).toSpanData().getParentSpanId()) .isEqualTo(rootSpan.getContext().getSpanId()); - assertThat(((SpanImpl) childSpan).toSpanData().getHasRemoteParent()).isFalse(); - assertThat(((SpanImpl) childSpan).getTimestampConverter()) - .isEqualTo(((SpanImpl) rootSpan).getTimestampConverter()); + assertThat(((RecordEventsSpanImpl) childSpan).toSpanData().getHasRemoteParent()).isFalse(); + assertThat(((RecordEventsSpanImpl) childSpan).getTimestampConverter()) + .isEqualTo(((RecordEventsSpanImpl) rootSpan).getTimestampConverter()); } @Test public void startRemoteSpan_NullParent() { - SpanImpl span = - SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, null, spanBuilderOptions).startSpan(); + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, null, spanBuilderOptions) + .setRecordEvents(true) + .startSpan(); assertThat(span.getContext().isValid()).isTrue(); assertThat(span.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); assertThat(span.getContext().getTraceOptions().isSampled()).isTrue(); @@ -153,9 +185,11 @@ public class SpanBuilderImplTest { @Test public void startRemoteSpanInvalidParent() { - SpanImpl span = - SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, SpanContext.INVALID, spanBuilderOptions) - .startSpan(); + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithRemoteParent( + SPAN_NAME, SpanContext.INVALID, spanBuilderOptions) + .startSpan(); assertThat(span.getContext().isValid()).isTrue(); assertThat(span.getOptions().contains(Options.RECORD_EVENTS)).isTrue(); assertThat(span.getContext().getTraceOptions().isSampled()).isTrue(); @@ -171,9 +205,11 @@ public class SpanBuilderImplTest { TraceId.generateRandomId(randomHandler.current()), SpanId.generateRandomId(randomHandler.current()), TraceOptions.DEFAULT); - SpanImpl span = - SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, spanContext, spanBuilderOptions) - .startSpan(); + RecordEventsSpanImpl span = + (RecordEventsSpanImpl) + SpanBuilderImpl.createWithRemoteParent(SPAN_NAME, spanContext, spanBuilderOptions) + .setRecordEvents(true) + .startSpan(); assertThat(span.getContext().isValid()).isTrue(); assertThat(span.getContext().getTraceId()).isEqualTo(spanContext.getTraceId()); assertThat(span.getContext().getTraceOptions().isSampled()).isTrue(); diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/SpanImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/SpanImplTest.java deleted file mode 100644 index 57818eea..00000000 --- a/impl_core/src/test/java/io/opencensus/implcore/trace/SpanImplTest.java +++ /dev/null @@ -1,639 +0,0 @@ -/* - * Copyright 2017, OpenCensus 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.opencensus.implcore.trace; - -import static com.google.common.truth.Truth.assertThat; - -import io.opencensus.common.Duration; -import io.opencensus.common.Timestamp; -import io.opencensus.implcore.internal.TimestampConverter; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; -import io.opencensus.testing.common.TestClock; -import io.opencensus.trace.Annotation; -import io.opencensus.trace.AttributeValue; -import io.opencensus.trace.EndSpanOptions; -import io.opencensus.trace.Link; -import io.opencensus.trace.NetworkEvent; -import io.opencensus.trace.Span.Kind; -import io.opencensus.trace.Span.Options; -import io.opencensus.trace.SpanContext; -import io.opencensus.trace.SpanId; -import io.opencensus.trace.Status; -import io.opencensus.trace.TraceId; -import io.opencensus.trace.TraceOptions; -import io.opencensus.trace.config.TraceParams; -import io.opencensus.trace.export.SpanData; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -/** Unit tests for {@link SpanImpl}. */ -@RunWith(JUnit4.class) -public class SpanImplTest { - private static final String SPAN_NAME = "MySpanName"; - private static final String ANNOTATION_DESCRIPTION = "MyAnnotation"; - private final Random random = new Random(1234); - private final SpanContext spanContext = - SpanContext.create( - TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); - private final SpanId parentSpanId = SpanId.generateRandomId(random); - private final Timestamp timestamp = Timestamp.create(1234, 5678); - private final TestClock testClock = TestClock.create(timestamp); - private final TimestampConverter timestampConverter = TimestampConverter.now(testClock); - private final EnumSet noRecordSpanOptions = EnumSet.noneOf(Options.class); - private final EnumSet recordSpanOptions = EnumSet.of(Options.RECORD_EVENTS); - private final Map attributes = new HashMap(); - private final Map expectedAttributes = - new HashMap(); - @Mock private StartEndHandler startEndHandler; - @Rule public final ExpectedException exception = ExpectedException.none(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - attributes.put( - "MyStringAttributeKey", AttributeValue.stringAttributeValue("MyStringAttributeValue")); - attributes.put("MyLongAttributeKey", AttributeValue.longAttributeValue(123L)); - attributes.put("MyBooleanAttributeKey", AttributeValue.booleanAttributeValue(false)); - expectedAttributes.putAll(attributes); - expectedAttributes.put( - "MySingleStringAttributeKey", - AttributeValue.stringAttributeValue("MySingleStringAttributeValue")); - } - - @Test - public void toSpanData_NoRecordEvents() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - noRecordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - // Check that adding trace events after Span#end() does not throw any exception. - span.putAttributes(attributes); - span.addAnnotation(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); - span.addAnnotation(ANNOTATION_DESCRIPTION, attributes); - span.addNetworkEvent( - NetworkEvent.builder(NetworkEvent.Type.RECV, 1).setUncompressedMessageSize(3).build()); - span.addLink(Link.fromSpanContext(spanContext, Link.Type.CHILD_LINKED_SPAN)); - span.end(); - exception.expect(IllegalStateException.class); - span.toSpanData(); - } - - @Test - public void noEventsRecordedAfterEnd() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - span.end(); - // Check that adding trace events after Span#end() does not throw any exception and are not - // recorded. - span.putAttributes(attributes); - span.putAttribute( - "MySingleStringAttributeKey", - AttributeValue.stringAttributeValue("MySingleStringAttributeValue")); - span.addAnnotation(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); - span.addAnnotation(ANNOTATION_DESCRIPTION, attributes); - span.addNetworkEvent( - NetworkEvent.builder(NetworkEvent.Type.RECV, 1).setUncompressedMessageSize(3).build()); - span.addLink(Link.fromSpanContext(spanContext, Link.Type.CHILD_LINKED_SPAN)); - SpanData spanData = span.toSpanData(); - assertThat(spanData.getStartTimestamp()).isEqualTo(timestamp); - assertThat(spanData.getAttributes().getAttributeMap()).isEmpty(); - assertThat(spanData.getAnnotations().getEvents()).isEmpty(); - assertThat(spanData.getNetworkEvents().getEvents()).isEmpty(); - assertThat(spanData.getLinks().getLinks()).isEmpty(); - assertThat(spanData.getStatus()).isEqualTo(Status.OK); - assertThat(spanData.getEndTimestamp()).isEqualTo(timestamp); - } - - @Test - public void deprecatedAddAttributesStillWorks() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - span.addAttributes(attributes); - span.end(); - SpanData spanData = span.toSpanData(); - assertThat(spanData.getAttributes().getAttributeMap()).isEqualTo(attributes); - } - - @Test - public void toSpanData_ActiveSpan() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - true, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - Mockito.verify(startEndHandler, Mockito.times(1)).onStart(span); - span.putAttribute( - "MySingleStringAttributeKey", - AttributeValue.stringAttributeValue("MySingleStringAttributeValue")); - span.putAttributes(attributes); - testClock.advanceTime(Duration.create(0, 100)); - span.addAnnotation(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); - testClock.advanceTime(Duration.create(0, 100)); - span.addAnnotation(ANNOTATION_DESCRIPTION, attributes); - testClock.advanceTime(Duration.create(0, 100)); - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.RECV, 1).setUncompressedMessageSize(3).build(); - span.addNetworkEvent(networkEvent); - testClock.advanceTime(Duration.create(0, 100)); - Link link = Link.fromSpanContext(spanContext, Link.Type.CHILD_LINKED_SPAN); - span.addLink(link); - SpanData spanData = span.toSpanData(); - assertThat(spanData.getContext()).isEqualTo(spanContext); - assertThat(spanData.getName()).isEqualTo(SPAN_NAME); - assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); - assertThat(spanData.getHasRemoteParent()).isTrue(); - assertThat(spanData.getAttributes().getDroppedAttributesCount()).isEqualTo(0); - assertThat(spanData.getAttributes().getAttributeMap()).isEqualTo(expectedAttributes); - assertThat(spanData.getAnnotations().getDroppedEventsCount()).isEqualTo(0); - assertThat(spanData.getAnnotations().getEvents().size()).isEqualTo(2); - assertThat(spanData.getAnnotations().getEvents().get(0).getTimestamp()) - .isEqualTo(timestamp.addNanos(100)); - assertThat(spanData.getAnnotations().getEvents().get(0).getEvent()) - .isEqualTo(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); - assertThat(spanData.getAnnotations().getEvents().get(1).getTimestamp()) - .isEqualTo(timestamp.addNanos(200)); - assertThat(spanData.getAnnotations().getEvents().get(1).getEvent()) - .isEqualTo(Annotation.fromDescriptionAndAttributes(ANNOTATION_DESCRIPTION, attributes)); - assertThat(spanData.getNetworkEvents().getDroppedEventsCount()).isEqualTo(0); - assertThat(spanData.getNetworkEvents().getEvents().size()).isEqualTo(1); - assertThat(spanData.getNetworkEvents().getEvents().get(0).getTimestamp()) - .isEqualTo(timestamp.addNanos(300)); - assertThat(spanData.getNetworkEvents().getEvents().get(0).getEvent()).isEqualTo(networkEvent); - assertThat(spanData.getLinks().getDroppedLinksCount()).isEqualTo(0); - assertThat(spanData.getLinks().getLinks().size()).isEqualTo(1); - assertThat(spanData.getLinks().getLinks().get(0)).isEqualTo(link); - assertThat(spanData.getStartTimestamp()).isEqualTo(timestamp); - assertThat(spanData.getStatus()).isNull(); - assertThat(spanData.getEndTimestamp()).isNull(); - } - - @Test - public void toSpanData_EndedSpan() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - Mockito.verify(startEndHandler, Mockito.times(1)).onStart(span); - span.putAttribute( - "MySingleStringAttributeKey", - AttributeValue.stringAttributeValue("MySingleStringAttributeValue")); - span.putAttributes(attributes); - testClock.advanceTime(Duration.create(0, 100)); - span.addAnnotation(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); - testClock.advanceTime(Duration.create(0, 100)); - span.addAnnotation(ANNOTATION_DESCRIPTION, attributes); - testClock.advanceTime(Duration.create(0, 100)); - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.RECV, 1).setUncompressedMessageSize(3).build(); - span.addNetworkEvent(networkEvent); - Link link = Link.fromSpanContext(spanContext, Link.Type.CHILD_LINKED_SPAN); - span.addLink(link); - testClock.advanceTime(Duration.create(0, 100)); - span.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); - Mockito.verify(startEndHandler, Mockito.times(1)).onEnd(span); - SpanData spanData = span.toSpanData(); - assertThat(spanData.getContext()).isEqualTo(spanContext); - assertThat(spanData.getName()).isEqualTo(SPAN_NAME); - assertThat(spanData.getParentSpanId()).isEqualTo(parentSpanId); - assertThat(spanData.getHasRemoteParent()).isFalse(); - assertThat(spanData.getAttributes().getDroppedAttributesCount()).isEqualTo(0); - assertThat(spanData.getAttributes().getAttributeMap()).isEqualTo(expectedAttributes); - assertThat(spanData.getAnnotations().getDroppedEventsCount()).isEqualTo(0); - assertThat(spanData.getAnnotations().getEvents().size()).isEqualTo(2); - assertThat(spanData.getAnnotations().getEvents().get(0).getTimestamp()) - .isEqualTo(timestamp.addNanos(100)); - assertThat(spanData.getAnnotations().getEvents().get(0).getEvent()) - .isEqualTo(Annotation.fromDescription(ANNOTATION_DESCRIPTION)); - assertThat(spanData.getAnnotations().getEvents().get(1).getTimestamp()) - .isEqualTo(timestamp.addNanos(200)); - assertThat(spanData.getAnnotations().getEvents().get(1).getEvent()) - .isEqualTo(Annotation.fromDescriptionAndAttributes(ANNOTATION_DESCRIPTION, attributes)); - assertThat(spanData.getNetworkEvents().getDroppedEventsCount()).isEqualTo(0); - assertThat(spanData.getNetworkEvents().getEvents().size()).isEqualTo(1); - assertThat(spanData.getNetworkEvents().getEvents().get(0).getTimestamp()) - .isEqualTo(timestamp.addNanos(300)); - assertThat(spanData.getNetworkEvents().getEvents().get(0).getEvent()).isEqualTo(networkEvent); - assertThat(spanData.getLinks().getDroppedLinksCount()).isEqualTo(0); - assertThat(spanData.getLinks().getLinks().size()).isEqualTo(1); - assertThat(spanData.getLinks().getLinks().get(0)).isEqualTo(link); - assertThat(spanData.getStartTimestamp()).isEqualTo(timestamp); - assertThat(spanData.getStatus()).isEqualTo(Status.CANCELLED); - assertThat(spanData.getEndTimestamp()).isEqualTo(timestamp.addNanos(400)); - } - - @Test - public void status_ViaSetStatus() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - Mockito.verify(startEndHandler, Mockito.times(1)).onStart(span); - testClock.advanceTime(Duration.create(0, 100)); - assertThat(span.getStatus()).isEqualTo(Status.OK); - span.setStatus(Status.CANCELLED); - assertThat(span.getStatus()).isEqualTo(Status.CANCELLED); - span.end(); - assertThat(span.getStatus()).isEqualTo(Status.CANCELLED); - } - - @Test - public void status_ViaEndSpanOptions() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - Mockito.verify(startEndHandler, Mockito.times(1)).onStart(span); - testClock.advanceTime(Duration.create(0, 100)); - assertThat(span.getStatus()).isEqualTo(Status.OK); - span.setStatus(Status.CANCELLED); - assertThat(span.getStatus()).isEqualTo(Status.CANCELLED); - span.end(EndSpanOptions.builder().setStatus(Status.ABORTED).build()); - assertThat(span.getStatus()).isEqualTo(Status.ABORTED); - } - - @Test - public void droppingAttributes() { - final int maxNumberOfAttributes = 8; - TraceParams traceParams = - TraceParams.DEFAULT.toBuilder().setMaxNumberOfAttributes(maxNumberOfAttributes).build(); - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - traceParams, - startEndHandler, - timestampConverter, - testClock); - for (int i = 0; i < 2 * maxNumberOfAttributes; i++) { - Map attributes = new HashMap(); - attributes.put("MyStringAttributeKey" + i, AttributeValue.longAttributeValue(i)); - span.putAttributes(attributes); - } - SpanData spanData = span.toSpanData(); - assertThat(spanData.getAttributes().getDroppedAttributesCount()) - .isEqualTo(maxNumberOfAttributes); - assertThat(spanData.getAttributes().getAttributeMap().size()).isEqualTo(maxNumberOfAttributes); - for (int i = 0; i < maxNumberOfAttributes; i++) { - assertThat( - spanData - .getAttributes() - .getAttributeMap() - .get("MyStringAttributeKey" + (i + maxNumberOfAttributes))) - .isEqualTo(AttributeValue.longAttributeValue(i + maxNumberOfAttributes)); - } - span.end(); - spanData = span.toSpanData(); - assertThat(spanData.getAttributes().getDroppedAttributesCount()) - .isEqualTo(maxNumberOfAttributes); - assertThat(spanData.getAttributes().getAttributeMap().size()).isEqualTo(maxNumberOfAttributes); - for (int i = 0; i < maxNumberOfAttributes; i++) { - assertThat( - spanData - .getAttributes() - .getAttributeMap() - .get("MyStringAttributeKey" + (i + maxNumberOfAttributes))) - .isEqualTo(AttributeValue.longAttributeValue(i + maxNumberOfAttributes)); - } - } - - @Test - public void droppingAndAddingAttributes() { - final int maxNumberOfAttributes = 8; - TraceParams traceParams = - TraceParams.DEFAULT.toBuilder().setMaxNumberOfAttributes(maxNumberOfAttributes).build(); - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - traceParams, - startEndHandler, - timestampConverter, - testClock); - for (int i = 0; i < 2 * maxNumberOfAttributes; i++) { - Map attributes = new HashMap(); - attributes.put("MyStringAttributeKey" + i, AttributeValue.longAttributeValue(i)); - span.putAttributes(attributes); - } - SpanData spanData = span.toSpanData(); - assertThat(spanData.getAttributes().getDroppedAttributesCount()) - .isEqualTo(maxNumberOfAttributes); - assertThat(spanData.getAttributes().getAttributeMap().size()).isEqualTo(maxNumberOfAttributes); - for (int i = 0; i < maxNumberOfAttributes; i++) { - assertThat( - spanData - .getAttributes() - .getAttributeMap() - .get("MyStringAttributeKey" + (i + maxNumberOfAttributes))) - .isEqualTo(AttributeValue.longAttributeValue(i + maxNumberOfAttributes)); - } - for (int i = 0; i < maxNumberOfAttributes / 2; i++) { - Map attributes = new HashMap(); - attributes.put("MyStringAttributeKey" + i, AttributeValue.longAttributeValue(i)); - span.putAttributes(attributes); - } - spanData = span.toSpanData(); - assertThat(spanData.getAttributes().getDroppedAttributesCount()) - .isEqualTo(maxNumberOfAttributes * 3 / 2); - assertThat(spanData.getAttributes().getAttributeMap().size()).isEqualTo(maxNumberOfAttributes); - // Test that we still have in the attributes map the latest maxNumberOfAttributes / 2 entries. - for (int i = 0; i < maxNumberOfAttributes / 2; i++) { - assertThat( - spanData - .getAttributes() - .getAttributeMap() - .get("MyStringAttributeKey" + (i + maxNumberOfAttributes * 3 / 2))) - .isEqualTo(AttributeValue.longAttributeValue(i + maxNumberOfAttributes * 3 / 2)); - } - // Test that we have the newest re-added initial entries. - for (int i = 0; i < maxNumberOfAttributes / 2; i++) { - assertThat(spanData.getAttributes().getAttributeMap().get("MyStringAttributeKey" + i)) - .isEqualTo(AttributeValue.longAttributeValue(i)); - } - } - - @Test - public void droppingAnnotations() { - final int maxNumberOfAnnotations = 8; - TraceParams traceParams = - TraceParams.DEFAULT.toBuilder().setMaxNumberOfAnnotations(maxNumberOfAnnotations).build(); - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - traceParams, - startEndHandler, - timestampConverter, - testClock); - Annotation annotation = Annotation.fromDescription(ANNOTATION_DESCRIPTION); - for (int i = 0; i < 2 * maxNumberOfAnnotations; i++) { - span.addAnnotation(annotation); - testClock.advanceTime(Duration.create(0, 100)); - } - SpanData spanData = span.toSpanData(); - assertThat(spanData.getAnnotations().getDroppedEventsCount()).isEqualTo(maxNumberOfAnnotations); - assertThat(spanData.getAnnotations().getEvents().size()).isEqualTo(maxNumberOfAnnotations); - for (int i = 0; i < maxNumberOfAnnotations; i++) { - assertThat(spanData.getAnnotations().getEvents().get(i).getTimestamp()) - .isEqualTo(timestamp.addNanos(100L * (maxNumberOfAnnotations + i))); - assertThat(spanData.getAnnotations().getEvents().get(i).getEvent()).isEqualTo(annotation); - } - span.end(); - spanData = span.toSpanData(); - assertThat(spanData.getAnnotations().getDroppedEventsCount()).isEqualTo(maxNumberOfAnnotations); - assertThat(spanData.getAnnotations().getEvents().size()).isEqualTo(maxNumberOfAnnotations); - for (int i = 0; i < maxNumberOfAnnotations; i++) { - assertThat(spanData.getAnnotations().getEvents().get(i).getTimestamp()) - .isEqualTo(timestamp.addNanos(100L * (maxNumberOfAnnotations + i))); - assertThat(spanData.getAnnotations().getEvents().get(i).getEvent()).isEqualTo(annotation); - } - } - - @Test - public void droppingNetworkEvents() { - final int maxNumberOfNetworkEvents = 8; - TraceParams traceParams = - TraceParams.DEFAULT - .toBuilder() - .setMaxNumberOfNetworkEvents(maxNumberOfNetworkEvents) - .build(); - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - traceParams, - startEndHandler, - timestampConverter, - testClock); - NetworkEvent networkEvent = - NetworkEvent.builder(NetworkEvent.Type.RECV, 1).setUncompressedMessageSize(3).build(); - for (int i = 0; i < 2 * maxNumberOfNetworkEvents; i++) { - span.addNetworkEvent(networkEvent); - testClock.advanceTime(Duration.create(0, 100)); - } - SpanData spanData = span.toSpanData(); - assertThat(spanData.getNetworkEvents().getDroppedEventsCount()) - .isEqualTo(maxNumberOfNetworkEvents); - assertThat(spanData.getNetworkEvents().getEvents().size()).isEqualTo(maxNumberOfNetworkEvents); - for (int i = 0; i < maxNumberOfNetworkEvents; i++) { - assertThat(spanData.getNetworkEvents().getEvents().get(i).getTimestamp()) - .isEqualTo(timestamp.addNanos(100L * (maxNumberOfNetworkEvents + i))); - assertThat(spanData.getNetworkEvents().getEvents().get(i).getEvent()).isEqualTo(networkEvent); - } - span.end(); - spanData = span.toSpanData(); - assertThat(spanData.getNetworkEvents().getDroppedEventsCount()) - .isEqualTo(maxNumberOfNetworkEvents); - assertThat(spanData.getNetworkEvents().getEvents().size()).isEqualTo(maxNumberOfNetworkEvents); - for (int i = 0; i < maxNumberOfNetworkEvents; i++) { - assertThat(spanData.getNetworkEvents().getEvents().get(i).getTimestamp()) - .isEqualTo(timestamp.addNanos(100L * (maxNumberOfNetworkEvents + i))); - assertThat(spanData.getNetworkEvents().getEvents().get(i).getEvent()).isEqualTo(networkEvent); - } - } - - @Test - public void droppingLinks() { - final int maxNumberOfLinks = 8; - TraceParams traceParams = - TraceParams.DEFAULT.toBuilder().setMaxNumberOfLinks(maxNumberOfLinks).build(); - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - traceParams, - startEndHandler, - timestampConverter, - testClock); - Link link = Link.fromSpanContext(spanContext, Link.Type.CHILD_LINKED_SPAN); - for (int i = 0; i < 2 * maxNumberOfLinks; i++) { - span.addLink(link); - } - SpanData spanData = span.toSpanData(); - assertThat(spanData.getLinks().getDroppedLinksCount()).isEqualTo(maxNumberOfLinks); - assertThat(spanData.getLinks().getLinks().size()).isEqualTo(maxNumberOfLinks); - for (int i = 0; i < maxNumberOfLinks; i++) { - assertThat(spanData.getLinks().getLinks().get(i)).isEqualTo(link); - } - span.end(); - spanData = span.toSpanData(); - assertThat(spanData.getLinks().getDroppedLinksCount()).isEqualTo(maxNumberOfLinks); - assertThat(spanData.getLinks().getLinks().size()).isEqualTo(maxNumberOfLinks); - for (int i = 0; i < maxNumberOfLinks; i++) { - assertThat(spanData.getLinks().getLinks().get(i)).isEqualTo(link); - } - } - - @Test - public void sampleToLocalSpanStore() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - span.end(EndSpanOptions.builder().setSampleToLocalSpanStore(true).build()); - Mockito.verify(startEndHandler, Mockito.times(1)).onEnd(span); - assertThat(span.getSampleToLocalSpanStore()).isTrue(); - span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - span.end(); - Mockito.verify(startEndHandler, Mockito.times(1)).onEnd(span); - assertThat(span.getSampleToLocalSpanStore()).isFalse(); - } - - @Test - public void sampleToLocalSpanStore_RunningSpan() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - null, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - exception.expect(IllegalStateException.class); - exception.expectMessage("Running span does not have the SampleToLocalSpanStore set."); - span.getSampleToLocalSpanStore(); - } - - @Test - public void getSpanKind() { - SpanImpl span = - SpanImpl.startSpan( - spanContext, - recordSpanOptions, - SPAN_NAME, - Kind.SERVER, - parentSpanId, - false, - TraceParams.DEFAULT, - startEndHandler, - timestampConverter, - testClock); - assertThat(span.getKind()).isEqualTo(Kind.SERVER); - } -} diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/TracerImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/TracerImplTest.java index 21143e3c..d10be6a2 100644 --- a/impl_core/src/test/java/io/opencensus/implcore/trace/TracerImplTest.java +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/TracerImplTest.java @@ -18,7 +18,7 @@ package io.opencensus.implcore.trace; import static com.google.common.truth.Truth.assertThat; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; import io.opencensus.implcore.trace.internal.RandomHandler.SecureRandomHandler; import io.opencensus.testing.common.TestClock; import io.opencensus.trace.BlankSpan; diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/export/InProcessRunningSpanStoreImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/export/InProcessRunningSpanStoreImplTest.java index 85db0868..68ce1c18 100644 --- a/impl_core/src/test/java/io/opencensus/implcore/trace/export/InProcessRunningSpanStoreImplTest.java +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/export/InProcessRunningSpanStoreImplTest.java @@ -21,17 +21,15 @@ import static com.google.common.truth.Truth.assertThat; import io.opencensus.common.Duration; import io.opencensus.implcore.common.MillisClock; import io.opencensus.implcore.internal.SimpleEventQueue; -import io.opencensus.implcore.trace.SpanImpl; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; import io.opencensus.implcore.trace.StartEndHandlerImpl; -import io.opencensus.trace.Span.Options; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.TraceId; import io.opencensus.trace.TraceOptions; import io.opencensus.trace.config.TraceParams; import io.opencensus.trace.export.RunningSpanStore.Filter; -import java.util.EnumSet; import java.util.Random; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,17 +49,15 @@ public class InProcessRunningSpanStoreImplTest { private final StartEndHandler startEndHandler = new StartEndHandlerImpl( sampledSpansServiceExporter, activeSpansExporter, null, new SimpleEventQueue()); - private final EnumSet recordSpanOptions = EnumSet.of(Options.RECORD_EVENTS); - private SpanImpl createSpan(String spanName) { + private RecordEventsSpanImpl createSpan(String spanName) { final SpanContext spanContext = SpanContext.create( TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); - return SpanImpl.startSpan( + return RecordEventsSpanImpl.startSpan( spanContext, - recordSpanOptions, spanName, null, SpanId.generateRandomId(random), @@ -74,8 +70,8 @@ public class InProcessRunningSpanStoreImplTest { @Test public void getSummary_SpansWithDifferentNames() { - final SpanImpl span1 = createSpan(SPAN_NAME_1); - final SpanImpl span2 = createSpan(SPAN_NAME_2); + final RecordEventsSpanImpl span1 = createSpan(SPAN_NAME_1); + final RecordEventsSpanImpl span2 = createSpan(SPAN_NAME_2); assertThat(activeSpansExporter.getSummary().getPerSpanNameSummary().size()).isEqualTo(2); assertThat( activeSpansExporter @@ -107,9 +103,9 @@ public class InProcessRunningSpanStoreImplTest { @Test public void getSummary_SpansWithSameName() { - final SpanImpl span1 = createSpan(SPAN_NAME_1); - final SpanImpl span2 = createSpan(SPAN_NAME_1); - final SpanImpl span3 = createSpan(SPAN_NAME_1); + final RecordEventsSpanImpl span1 = createSpan(SPAN_NAME_1); + final RecordEventsSpanImpl span2 = createSpan(SPAN_NAME_1); + final RecordEventsSpanImpl span3 = createSpan(SPAN_NAME_1); assertThat(activeSpansExporter.getSummary().getPerSpanNameSummary().size()).isEqualTo(1); assertThat( activeSpansExporter @@ -142,8 +138,8 @@ public class InProcessRunningSpanStoreImplTest { @Test public void getActiveSpans_SpansWithDifferentNames() { - SpanImpl span1 = createSpan(SPAN_NAME_1); - SpanImpl span2 = createSpan(SPAN_NAME_2); + RecordEventsSpanImpl span1 = createSpan(SPAN_NAME_1); + RecordEventsSpanImpl span2 = createSpan(SPAN_NAME_2); assertThat(activeSpansExporter.getRunningSpans(Filter.create(SPAN_NAME_1, 0))) .containsExactly(span1.toSpanData()); assertThat(activeSpansExporter.getRunningSpans(Filter.create(SPAN_NAME_1, 2))) @@ -156,9 +152,9 @@ public class InProcessRunningSpanStoreImplTest { @Test public void getActiveSpans_SpansWithSameName() { - SpanImpl span1 = createSpan(SPAN_NAME_1); - SpanImpl span2 = createSpan(SPAN_NAME_1); - SpanImpl span3 = createSpan(SPAN_NAME_1); + RecordEventsSpanImpl span1 = createSpan(SPAN_NAME_1); + RecordEventsSpanImpl span2 = createSpan(SPAN_NAME_1); + RecordEventsSpanImpl span3 = createSpan(SPAN_NAME_1); assertThat(activeSpansExporter.getRunningSpans(Filter.create(SPAN_NAME_1, 0))) .containsExactly(span1.toSpanData(), span2.toSpanData(), span3.toSpanData()); assertThat(activeSpansExporter.getRunningSpans(Filter.create(SPAN_NAME_1, 2)).size()) diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/export/InProcessSampledSpanStoreImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/export/InProcessSampledSpanStoreImplTest.java index e1d2c4bb..7d8b434e 100644 --- a/impl_core/src/test/java/io/opencensus/implcore/trace/export/InProcessSampledSpanStoreImplTest.java +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/export/InProcessSampledSpanStoreImplTest.java @@ -21,12 +21,11 @@ import static com.google.common.truth.Truth.assertThat; import io.opencensus.common.Duration; import io.opencensus.common.Timestamp; import io.opencensus.implcore.internal.SimpleEventQueue; -import io.opencensus.implcore.trace.SpanImpl; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; import io.opencensus.testing.common.TestClock; import io.opencensus.trace.EndSpanOptions; import io.opencensus.trace.Span; -import io.opencensus.trace.Span.Options; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.Status; @@ -41,7 +40,6 @@ import io.opencensus.trace.export.SampledSpanStore.PerSpanNameSummary; import io.opencensus.trace.export.SpanData; import java.util.Collection; import java.util.Collections; -import java.util.EnumSet; import java.util.Map; import java.util.Random; import java.util.concurrent.TimeUnit; @@ -66,19 +64,18 @@ public class InProcessSampledSpanStoreImplTest { SpanContext.create( TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); private final SpanId parentSpanId = SpanId.generateRandomId(random); - private final EnumSet recordSpanOptions = EnumSet.of(Options.RECORD_EVENTS); private final TestClock testClock = TestClock.create(Timestamp.create(12345, 54321)); private final InProcessSampledSpanStoreImpl sampleStore = new InProcessSampledSpanStoreImpl(new SimpleEventQueue()); private final StartEndHandler startEndHandler = new StartEndHandler() { @Override - public void onStart(SpanImpl span) { + public void onStart(RecordEventsSpanImpl span) { // Do nothing. } @Override - public void onEnd(SpanImpl span) { + public void onEnd(RecordEventsSpanImpl span) { sampleStore.considerForSampling(span); } }; @@ -88,10 +85,9 @@ public class InProcessSampledSpanStoreImplTest { sampleStore.registerSpanNamesForCollection(Collections.singletonList(REGISTERED_SPAN_NAME)); } - private SpanImpl createSampledSpan(String spanName) { - return SpanImpl.startSpan( + private RecordEventsSpanImpl createSampledSpan(String spanName) { + return RecordEventsSpanImpl.startSpan( sampledSpanContext, - recordSpanOptions, spanName, null, parentSpanId, @@ -102,10 +98,9 @@ public class InProcessSampledSpanStoreImplTest { testClock); } - private SpanImpl createNotSampledSpan(String spanName) { - return SpanImpl.startSpan( + private RecordEventsSpanImpl createNotSampledSpan(String spanName) { + return RecordEventsSpanImpl.startSpan( notSampledSpanContext, - recordSpanOptions, spanName, null, parentSpanId, @@ -216,7 +211,7 @@ public class InProcessSampledSpanStoreImplTest { @Test public void getErrorSampledSpans() { - SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); Collection samples = @@ -228,12 +223,12 @@ public class InProcessSampledSpanStoreImplTest { @Test public void getErrorSampledSpans_MaxSpansToReturn() { - SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span1.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); // Advance time to allow other spans to be sampled. testClock.advanceTime(Duration.create(5, 0)); - SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span2.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); Collection samples = @@ -246,10 +241,10 @@ public class InProcessSampledSpanStoreImplTest { @Test public void getErrorSampledSpans_NullCode() { - SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span1.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); - SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span2.end(EndSpanOptions.builder().setStatus(Status.UNKNOWN).build()); Collection samples = @@ -260,10 +255,10 @@ public class InProcessSampledSpanStoreImplTest { @Test public void getErrorSampledSpans_NullCode_MaxSpansToReturn() { - SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span1.end(EndSpanOptions.builder().setStatus(Status.CANCELLED).build()); - SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, 1000)); span2.end(EndSpanOptions.builder().setStatus(Status.UNKNOWN).build()); Collection samples = @@ -274,7 +269,7 @@ public class InProcessSampledSpanStoreImplTest { @Test public void getLatencySampledSpans() { - SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span.end(); Collection samples = @@ -290,7 +285,7 @@ public class InProcessSampledSpanStoreImplTest { @Test public void getLatencySampledSpans_ExclusiveUpperBound() { - SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span.end(); Collection samples = @@ -305,7 +300,7 @@ public class InProcessSampledSpanStoreImplTest { @Test public void getLatencySampledSpans_InclusiveLowerBound() { - SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span.end(); Collection samples = @@ -321,12 +316,12 @@ public class InProcessSampledSpanStoreImplTest { @Test public void getLatencySampledSpans_QueryBetweenMultipleBuckets() { - SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span1.end(); // Advance time to allow other spans to be sampled. testClock.advanceTime(Duration.create(5, 0)); - SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(200))); span2.end(); Collection samples = @@ -341,12 +336,12 @@ public class InProcessSampledSpanStoreImplTest { @Test public void getLatencySampledSpans_MaxSpansToReturn() { - SpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span1 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(20))); span1.end(); // Advance time to allow other spans to be sampled. testClock.advanceTime(Duration.create(5, 0)); - SpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span2 = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(200))); span2.end(); Collection samples = @@ -362,7 +357,7 @@ public class InProcessSampledSpanStoreImplTest { @Test public void ignoreNegativeSpanLatency() { - SpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); + RecordEventsSpanImpl span = createSampledSpan(REGISTERED_SPAN_NAME); testClock.advanceTime(Duration.create(0, (int) TimeUnit.MICROSECONDS.toNanos(-20))); span.end(); Collection samples = diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/export/NoopRunningSpanStoreImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/export/NoopRunningSpanStoreImplTest.java index 2877bb33..96669df7 100644 --- a/impl_core/src/test/java/io/opencensus/implcore/trace/export/NoopRunningSpanStoreImplTest.java +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/export/NoopRunningSpanStoreImplTest.java @@ -22,17 +22,15 @@ import io.opencensus.common.Timestamp; import io.opencensus.implcore.internal.EventQueue; import io.opencensus.implcore.internal.SimpleEventQueue; import io.opencensus.implcore.internal.TimestampConverter; -import io.opencensus.implcore.trace.SpanImpl; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; import io.opencensus.testing.common.TestClock; -import io.opencensus.trace.Span.Options; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.TraceId; import io.opencensus.trace.TraceOptions; import io.opencensus.trace.config.TraceParams; import io.opencensus.trace.export.RunningSpanStore.Filter; -import java.util.EnumSet; import java.util.Random; import org.junit.Before; import org.junit.Test; @@ -54,9 +52,8 @@ public class NoopRunningSpanStoreImplTest { TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); private final TestClock testClock = TestClock.create(timestamp); private final TimestampConverter timestampConverter = TimestampConverter.now(testClock); - private final EnumSet recordSpanOptions = EnumSet.of(Options.RECORD_EVENTS); @Mock private StartEndHandler startEndHandler; - private SpanImpl spanImpl; + private RecordEventsSpanImpl recordEventsSpanImpl; // maxSpansToReturn=0 means all private final Filter filter = Filter.create(SPAN_NAME, 0 /* maxSpansToReturn */); private final EventQueue eventQueue = new SimpleEventQueue(); @@ -66,10 +63,9 @@ public class NoopRunningSpanStoreImplTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - spanImpl = - SpanImpl.startSpan( + recordEventsSpanImpl = + RecordEventsSpanImpl.startSpan( spanContext, - recordSpanOptions, SPAN_NAME, null, null, @@ -90,10 +86,10 @@ public class NoopRunningSpanStoreImplTest { public void noopImplementation() { getMethodsShouldReturnEmpty(); // onStart() does not affect the result. - runningSpanStoreImpl.onStart(spanImpl); + runningSpanStoreImpl.onStart(recordEventsSpanImpl); getMethodsShouldReturnEmpty(); // onEnd() does not affect the result. - runningSpanStoreImpl.onEnd(spanImpl); + runningSpanStoreImpl.onEnd(recordEventsSpanImpl); getMethodsShouldReturnEmpty(); } } diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/export/NoopSampledSpanStoreImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/export/NoopSampledSpanStoreImplTest.java index 3ba33fd1..b9fbd432 100644 --- a/impl_core/src/test/java/io/opencensus/implcore/trace/export/NoopSampledSpanStoreImplTest.java +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/export/NoopSampledSpanStoreImplTest.java @@ -22,10 +22,9 @@ import io.opencensus.common.Timestamp; import io.opencensus.implcore.internal.EventQueue; import io.opencensus.implcore.internal.SimpleEventQueue; import io.opencensus.implcore.internal.TimestampConverter; -import io.opencensus.implcore.trace.SpanImpl; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; import io.opencensus.testing.common.TestClock; -import io.opencensus.trace.Span.Options; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.TraceId; @@ -35,7 +34,6 @@ import io.opencensus.trace.export.SampledSpanStore.ErrorFilter; import io.opencensus.trace.export.SampledSpanStore.LatencyFilter; import java.util.Collection; import java.util.Collections; -import java.util.EnumSet; import java.util.Random; import org.junit.Before; import org.junit.Test; @@ -59,9 +57,8 @@ public final class NoopSampledSpanStoreImplTest { TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); private final TestClock testClock = TestClock.create(timestamp); private final TimestampConverter timestampConverter = TimestampConverter.now(testClock); - private final EnumSet recordSpanOptions = EnumSet.of(Options.RECORD_EVENTS); @Mock private StartEndHandler startEndHandler; - private SpanImpl spanImpl; + private RecordEventsSpanImpl recordEventsSpanImpl; // maxSpansToReturn=0 means all private final ErrorFilter errorFilter = ErrorFilter.create(SPAN_NAME, null /* canonicalCode */, 0 /* maxSpansToReturn */); @@ -99,10 +96,9 @@ public final class NoopSampledSpanStoreImplTest { // considerForSampling() should do nothing and do not affect the result. // It should be called after registerSpanNamesForCollection. - spanImpl = - SpanImpl.startSpan( + recordEventsSpanImpl = + RecordEventsSpanImpl.startSpan( spanContext, - recordSpanOptions, SPAN_NAME, null, null, @@ -111,8 +107,8 @@ public final class NoopSampledSpanStoreImplTest { startEndHandler, timestampConverter, testClock); - spanImpl.end(); - sampledSpanStoreImpl.considerForSampling(spanImpl); + recordEventsSpanImpl.end(); + sampledSpanStoreImpl.considerForSampling(recordEventsSpanImpl); getMethodsShouldReturnEmpty(); // unregisterSpanNamesForCollection() should do nothing and do not affect the result. diff --git a/impl_core/src/test/java/io/opencensus/implcore/trace/export/SpanExporterImplTest.java b/impl_core/src/test/java/io/opencensus/implcore/trace/export/SpanExporterImplTest.java index d99776d1..f8f1d917 100644 --- a/impl_core/src/test/java/io/opencensus/implcore/trace/export/SpanExporterImplTest.java +++ b/impl_core/src/test/java/io/opencensus/implcore/trace/export/SpanExporterImplTest.java @@ -23,11 +23,10 @@ import static org.mockito.Mockito.doThrow; import io.opencensus.common.Duration; import io.opencensus.implcore.common.MillisClock; import io.opencensus.implcore.internal.SimpleEventQueue; -import io.opencensus.implcore.trace.SpanImpl; -import io.opencensus.implcore.trace.SpanImpl.StartEndHandler; +import io.opencensus.implcore.trace.RecordEventsSpanImpl; +import io.opencensus.implcore.trace.RecordEventsSpanImpl.StartEndHandler; import io.opencensus.implcore.trace.StartEndHandlerImpl; import io.opencensus.testing.export.TestHandler; -import io.opencensus.trace.Span.Options; import io.opencensus.trace.SpanContext; import io.opencensus.trace.SpanId; import io.opencensus.trace.TraceId; @@ -35,7 +34,6 @@ import io.opencensus.trace.TraceOptions; import io.opencensus.trace.config.TraceParams; import io.opencensus.trace.export.SpanData; import io.opencensus.trace.export.SpanExporter.Handler; -import java.util.EnumSet; import java.util.List; import java.util.Random; import org.junit.Before; @@ -60,7 +58,6 @@ public class SpanExporterImplTest { SpanContext.create( TraceId.generateRandomId(random), SpanId.generateRandomId(random), TraceOptions.DEFAULT); private final RunningSpanStoreImpl runningSpanStore = new InProcessRunningSpanStoreImpl(); - private final EnumSet recordSpanOptions = EnumSet.of(Options.RECORD_EVENTS); private final TestHandler serviceHandler = new TestHandler(); @Mock private Handler mockServiceHandler; @@ -69,11 +66,11 @@ public class SpanExporterImplTest { MockitoAnnotations.initMocks(this); } - private SpanImpl createSampledEndedSpan(StartEndHandler startEndHandler, String spanName) { - SpanImpl span = - SpanImpl.startSpan( + private RecordEventsSpanImpl createSampledEndedSpan( + StartEndHandler startEndHandler, String spanName) { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( sampledSpanContext, - recordSpanOptions, spanName, null, null, @@ -86,11 +83,11 @@ public class SpanExporterImplTest { return span; } - private SpanImpl createNotSampledEndedSpan(StartEndHandler startEndHandler, String spanName) { - SpanImpl span = - SpanImpl.startSpan( + private RecordEventsSpanImpl createNotSampledEndedSpan( + StartEndHandler startEndHandler, String spanName) { + RecordEventsSpanImpl span = + RecordEventsSpanImpl.startSpan( notSampledSpanContext, - recordSpanOptions, spanName, null, null, @@ -111,8 +108,8 @@ public class SpanExporterImplTest { spanExporter.registerHandler("test.service", serviceHandler); - SpanImpl span1 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); - SpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_2); + RecordEventsSpanImpl span1 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_2); List exported = serviceHandler.waitForExport(2); assertThat(exported).containsExactly(span1.toSpanData(), span2.toSpanData()); } @@ -125,12 +122,12 @@ public class SpanExporterImplTest { spanExporter.registerHandler("test.service", serviceHandler); - SpanImpl span1 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); - SpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); - SpanImpl span3 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); - SpanImpl span4 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); - SpanImpl span5 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); - SpanImpl span6 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span1 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span3 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span4 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span5 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span6 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); List exported = serviceHandler.waitForExport(6); assertThat(exported) .containsExactly( @@ -167,11 +164,11 @@ public class SpanExporterImplTest { spanExporter.registerHandler("test.service", serviceHandler); spanExporter.registerHandler("mock.service", mockServiceHandler); - SpanImpl span1 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span1 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); List exported = serviceHandler.waitForExport(1); assertThat(exported).containsExactly(span1.toSpanData()); // Continue to export after the exception was received. - SpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); exported = serviceHandler.waitForExport(1); assertThat(exported).containsExactly(span2.toSpanData()); } @@ -186,8 +183,8 @@ public class SpanExporterImplTest { TestHandler serviceHandler2 = new TestHandler(); spanExporter.registerHandler("test.service2", serviceHandler2); - SpanImpl span1 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); - SpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_2); + RecordEventsSpanImpl span1 = createSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_2); List exported1 = serviceHandler.waitForExport(2); List exported2 = serviceHandler2.waitForExport(2); assertThat(exported1).containsExactly(span1.toSpanData(), span2.toSpanData()); @@ -202,8 +199,8 @@ public class SpanExporterImplTest { spanExporter.registerHandler("test.service", serviceHandler); - SpanImpl span1 = createNotSampledEndedSpan(startEndHandler, SPAN_NAME_1); - SpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_2); + RecordEventsSpanImpl span1 = createNotSampledEndedSpan(startEndHandler, SPAN_NAME_1); + RecordEventsSpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_2); // Spans are recorded and exported in the same order as they are ended, we test that a non // sampled span is not exported by creating and ending a sampled span after a non sampled span // and checking that the first exported span is the sampled span (the non sampled did not get @@ -224,7 +221,7 @@ public class SpanExporterImplTest { spanExporter.registerHandler("test.service", serviceHandler); - SpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_2); + RecordEventsSpanImpl span2 = createSampledEndedSpan(startEndHandler, SPAN_NAME_2); // Force a flush, without this, the #waitForExport() call below would block indefinitely. spanExporter.flush(); -- cgit v1.2.3