
io.opentelemetry.trace.Span Maven / Gradle / Ivy
Show all versions of lightstep-opentelemetry-auto-exporter Show documentation
/*
* Copyright 2019, OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.opentelemetry.trace;
import shaded.shaded.io.grpc.Context;
import io.opentelemetry.common.AttributeValue;
import io.opentelemetry.common.Attributes;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
/**
* An interface that represents a span. It has an associated {@link SpanContext}.
*
* Spans are created by the {@link Builder#startSpan} method.
*
*
{@code Span} must be ended by calling {@link #end()}.
*
* @since 0.1.0
*/
@ThreadSafe
public interface Span {
/**
* Type of span. Can be used to specify additional relationships between spans in addition to a
* parent/child relationship.
*
* @since 0.1.0
*/
enum Kind {
/**
* Default value. Indicates that the span is used internally.
*
* @since 0.1.0
*/
INTERNAL,
/**
* Indicates that the span covers server-side handling of an RPC or other remote request.
*
* @since 0.1.0
*/
SERVER,
/**
* Indicates that the span covers the client-side wrapper around an RPC or other remote request.
*
* @since 0.1.0
*/
CLIENT,
/**
* Indicates that the span describes producer sending a message to a broker. Unlike client and
* server, there is no direct critical path latency relationship between producer and consumer
* spans.
*
* @since 0.1.0
*/
PRODUCER,
/**
* Indicates that the span describes consumer receiving a message from a broker. Unlike client
* and server, there is no direct critical path latency relationship between producer and
* consumer spans.
*
* @since 0.1.0
*/
CONSUMER
}
/**
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for
* the key, the old value is replaced by the specified value.
*
*
If a null or empty String {@code value} is passed in, the attribute will be silently
* dropped. Note: this behavior could change in the future.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @since 0.1.0
*/
void setAttribute(String key, @Nullable String value);
/**
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for
* the key, the old value is replaced by the specified value.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @since 0.1.0
*/
void setAttribute(String key, long value);
/**
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for
* the key, the old value is replaced by the specified value.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @since 0.1.0
*/
void setAttribute(String key, double value);
/**
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for
* the key, the old value is replaced by the specified value.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @since 0.1.0
*/
void setAttribute(String key, boolean value);
/**
* Sets an attribute to the {@code Span}. If the {@code Span} previously contained a mapping for
* the key, the old value is replaced by the specified value.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @since 0.1.0
*/
void setAttribute(String key, AttributeValue value);
/**
* Adds an event to the {@code Span}.
*
* @param name the name of the event.
* @since 0.1.0
*/
void addEvent(String name);
/**
* Adds an event to the {@code Span}.
*
*
Use this method to specify an explicit event timestamp. If not called, the implementation
* will use the current timestamp value, which should be the default case.
*
*
Important: this is NOT equivalent with System.nanoTime().
*
* @param name the name of the event.
* @param timestamp the explicit event timestamp in nanos since epoch.
* @since 0.1.0
*/
void addEvent(String name, long timestamp);
/**
* Adds an event to the {@code Span}.
*
* @param name the name of the event.
* @param attributes the attributes that will be added; these are associated with this event, not
* the {@code Span} as for {@code setAttribute()}.
* @since 0.1.0
*/
void addEvent(String name, Attributes attributes);
/**
* Adds an event to the {@code Span}.
*
*
Use this method to specify an explicit event timestamp. If not called, the implementation
* will use the current timestamp value, which should be the default case.
*
*
Important: this is NOT equivalent with System.nanoTime().
*
* @param name the name of the event.
* @param attributes the attributes that will be added; these are associated with this event, not
* the {@code Span} as for {@code setAttribute()}.
* @param timestamp the explicit event timestamp in nanos since epoch.
* @since 0.1.0
*/
void addEvent(String name, Attributes attributes, long timestamp);
/**
* Adds an event to the {@code Span}.
*
* @param event the event to add.
* @since 0.1.0
*/
void addEvent(Event event);
/**
* Adds an event to the {@code Span}.
*
*
Use this method to specify an explicit event timestamp. If not called, the implementation
* will use the current timestamp value, which should be the default case.
*
*
Important: this is NOT equivalent with System.nanoTime().
*
* @param event the event to add.
* @param timestamp the explicit event timestamp in nanos since epoch.
* @since 0.1.0
*/
void addEvent(Event event, long timestamp);
/**
* Sets the {@link Status} to the {@code Span}.
*
*
If used, this will override the default {@code Span} status. Default is {@link Status#OK}.
*
*
Only the value of the last call will be recorded, and implementations are free to ignore
* previous calls.
*
* @param status the {@link Status} to set.
* @since 0.1.0
*/
void setStatus(Status status);
/**
* Records information about the {@link Throwable} to the {@link Span}.
*
* @param exception the {@link Throwable} to record.
* @since 0.7.0
*/
void recordException(Throwable exception);
/**
* Updates the {@code Span} name.
*
*
If used, this will override the name provided via {@code Span.Builder}.
*
*
Upon this update, any sampling behavior based on {@code Span} name will depend on the
* implementation.
*
* @param name the {@code Span} name.
* @since 0.1
*/
void updateName(String name);
/**
* Marks the end of {@code Span} execution.
*
*
Only the timing of the first end call for a given {@code Span} will be recorded, and
* implementations are free to ignore all further calls.
*
* @since 0.1.0
*/
void end();
/**
* Marks the end of {@code Span} execution with the specified {@link EndSpanOptions}.
*
*
Only the timing of the first end call for a given {@code Span} will be recorded, and
* implementations are free to ignore all further calls.
*
*
Use this method for specifying explicit end options, such as end {@code Timestamp}. When no
* explicit values are required, use {@link #end()}.
*
* @param endOptions the explicit {@link EndSpanOptions} for this {@code Span}.
* @since 0.1.0
*/
void end(EndSpanOptions endOptions);
/**
* Returns the {@code SpanContext} associated with this {@code Span}.
*
* @return the {@code SpanContext} associated with this {@code Span}.
* @since 0.1.0
*/
SpanContext getContext();
/**
* Returns {@code true} if this {@code Span} records tracing events (e.g. {@link
* #addEvent(String)}, {@link #setAttribute(String, long)}).
*
* @return {@code true} if this {@code Span} records tracing events.
* @since 0.1.0
*/
boolean isRecording();
/**
* {@link Builder} is used to construct {@link Span} instances which define arbitrary scopes of
* code that are sampled for distributed tracing as a single atomic unit.
*
*
This is a simple example where all the work is being done within a single scope and a single
* thread and the Context is automatically propagated:
*
*
{@code
* class MyClass {
* private static final Tracer tracer = OpenTelemetry.getTracer();
* void doWork {
* // Create a Span as a child of the current Span.
* Span span = tracer.spanBuilder("MyChildSpan").startSpan();
* try (Scope ss = tracer.withSpan(span)) {
* tracer.getCurrentSpan().addEvent("my event");
* doSomeWork(); // Here the new span is in the current Context, so it can be used
* // implicitly anywhere down the stack.
* } finally {
* span.end();
* }
* }
* }
* }
*
* There might be cases where you do not perform all the work inside one static scope and the
* Context is automatically propagated:
*
*
{@code
* class MyRpcServerInterceptorListener implements RpcServerInterceptor.Listener {
* private static final Tracer tracer = OpenTelemetry.getTracer();
* private Span mySpan;
*
* public MyRpcInterceptor() {}
*
* public void onRequest(String rpcName, Metadata metadata) {
* // Create a Span as a child of the remote Span.
* mySpan = tracer.spanBuilder(rpcName)
* .setParent(getTraceContextFromMetadata(metadata)).startSpan();
* }
*
* public void onExecuteHandler(ServerCallHandler serverCallHandler) {
* try (Scope ws = tracer.withSpan(mySpan)) {
* tracer.getCurrentSpan().addEvent("Start rpc execution.");
* serverCallHandler.run(); // Here the new span is in the current Context, so it can be
* // used implicitly anywhere down the stack.
* }
* }
*
* // Called when the RPC is canceled and guaranteed onComplete will not be called.
* public void onCancel() {
* // IMPORTANT: DO NOT forget to ended the Span here as the work is done.
* mySpan.setStatus(Status.CANCELLED);
* mySpan.end();
* }
*
* // Called when the RPC is done and guaranteed onCancel will not be called.
* public void onComplete(RpcStatus rpcStatus) {
* // IMPORTANT: DO NOT forget to ended the Span here as the work is done.
* mySpan.setStatus(rpcStatusToCanonicalTraceStatus(status);
* mySpan.end();
* }
* }
* }
*
* This is a simple example where all the work is being done within a single scope and the
* Context is manually propagated:
*
*
{@code
* class MyClass {
* private static final Tracer tracer = OpenTelemetry.getTracer();
* void DoWork(Span parent) {
* Span childSpan = tracer.spanBuilder("MyChildSpan")
* .setParent(parent).startSpan();
* childSpan.addEvent("my event");
* try {
* doSomeWork(childSpan); // Manually propagate the new span down the stack.
* } finally {
* // To make sure we end the span even in case of an exception.
* childSpan.end(); // Manually end the span.
* }
* }
* }
* }
*
* If your Java version is less than Java SE 7, see {@link Builder#startSpan} for usage
* examples.
*
* @since 0.1.0
*/
interface Builder {
/**
* Sets the parent {@code Span} to use. If not set, the value of {@code Tracer.getCurrentSpan()}
* at {@link #startSpan()} time will be used as parent.
*
*
This must be used to create a {@code Span} when manual Context propagation is used
* OR when creating a root {@code Span} with a parent with an invalid {@link SpanContext}.
*
*
Observe this is the preferred method when the parent is a {@code Span} created within the
* process. Using its {@code SpanContext} as parent remains as a valid, albeit inefficient,
* operation.
*
*
If called multiple times, only the last specified value will be used. Observe that the
* state defined by a previous call to {@link #setNoParent()} will be discarded.
*
* @param parent the {@code Span} used as parent.
* @return this.
* @throws NullPointerException if {@code parent} is {@code null}.
* @see #setNoParent()
* @since 0.1.0
*/
Builder setParent(Span parent);
/**
* Sets the parent {@link SpanContext} to use. If not set, the value of {@code
* Tracer.getCurrentSpan()} at {@link #startSpan()} time will be used as parent.
*
*
Similar to {@link #setParent(Span parent)} but this must be used to create a {@code
* Span} when the parent is in a different process. This is only intended for use by RPC systems
* or similar.
*
*
If no {@link SpanContext} is available, users must call {@link #setNoParent()} in order to
* create a root {@code Span} for a new trace.
*
*
If called multiple times, only the last specified value will be used. Observe that the
* state defined by a previous call to {@link #setNoParent()} will be discarded.
*
* @param remoteParent the {@link SpanContext} used as parent.
* @return this.
* @throws NullPointerException if {@code remoteParent} is {@code null}.
* @see #setParent(Span parent)
* @see #setNoParent()
* @since 0.1.0
*/
Builder setParent(SpanContext remoteParent);
/**
* Sets the parent to use from the specified {@code Context}. If not set, the value of {@code
* Tracer.getCurrentSpan()} at {@link #startSpan()} time will be used as parent.
*
*
If no {@link Span} is available in the specified {@code Context}, the resulting {@code
* Span} will become a root instance, as if {@link #setNoParent()} had been called.
*
*
If called multiple times, only the last specified value will be used. Observe that the
* state defined by a previous call to {@link #setNoParent()} will be discarded.
*
* @param context the {@code Context}.
* @return this.
* @throws NullPointerException if {@code context} is {@code null}.
* @since 0.7.0
*/
Builder setParent(Context context);
/**
* Sets the option to become a root {@code Span} for a new trace. If not set, the value of
* {@code Tracer.getCurrentSpan()} at {@link #startSpan()} time will be used as parent.
*
*
Observe that any previously set parent will be discarded.
*
* @return this.
* @since 0.1.0
*/
Builder setNoParent();
/**
* Adds a {@link Link} to the newly created {@code Span}.
*
* @param spanContext the context of the linked {@code Span}.
* @return this.
* @throws NullPointerException if {@code spanContext} is {@code null}.
* @see #addLink(Link)
* @since 0.1.0
*/
Builder addLink(SpanContext spanContext);
/**
* Adds a {@link Link} to the newly created {@code Span}.
*
* @param spanContext the context of the linked {@code Span}.
* @param attributes the attributes of the {@code Link}.
* @return this.
* @throws NullPointerException if {@code spanContext} is {@code null}.
* @throws NullPointerException if {@code attributes} is {@code null}.
* @see #addLink(Link)
* @since 0.1.0
*/
Builder addLink(SpanContext spanContext, Attributes attributes);
/**
* Adds a {@link Link} to the newly created {@code Span}.
*
*
Links are used to link {@link Span}s in different traces. Used (for example) in batching
* operations, where a single batch handler processes multiple requests from different traces or
* the same trace.
*
* @param link the {@link Link} to be added.
* @return this.
* @throws NullPointerException if {@code link} is {@code null}.
* @since 0.1.0
*/
Builder addLink(Link link);
/**
* Sets an attribute to the newly created {@code Span}. If {@code Span.Builder} previously
* contained a mapping for the key, the old value is replaced by the specified value.
*
*
If a null or empty String {@code value} is passed in, the attribute will be silently
* dropped. Note: this behavior could change in the future.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
* @throws NullPointerException if {@code key} is {@code null}.
* @since 0.3.0
*/
Builder setAttribute(String key, @Nullable String value);
/**
* Sets an attribute to the newly created {@code Span}. If {@code Span.Builder} previously
* contained a mapping for the key, the old value is replaced by the specified value.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
* @throws NullPointerException if {@code key} is {@code null}.
* @since 0.3.0
*/
Builder setAttribute(String key, long value);
/**
* Sets an attribute to the newly created {@code Span}. If {@code Span.Builder} previously
* contained a mapping for the key, the old value is replaced by the specified value.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
* @throws NullPointerException if {@code key} is {@code null}.
* @since 0.3.0
*/
Builder setAttribute(String key, double value);
/**
* Sets an attribute to the newly created {@code Span}. If {@code Span.Builder} previously
* contained a mapping for the key, the old value is replaced by the specified value.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
* @throws NullPointerException if {@code key} is {@code null}.
* @since 0.3.0
*/
Builder setAttribute(String key, boolean value);
/**
* Sets an attribute to the newly created {@code Span}. If {@code Span.Builder} previously
* contained a mapping for the key, the old value is replaced by the specified value.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
* @throws NullPointerException if {@code key} is {@code null}.
* @throws NullPointerException if {@code value} is {@code null}.
* @since 0.3.0
*/
Builder setAttribute(String key, AttributeValue value);
/**
* Sets the {@link Span.Kind} for the newly created {@code Span}. If not called, the
* implementation will provide a default value {@link Span.Kind#INTERNAL}.
*
* @param spanKind the kind of the newly created {@code Span}.
* @return this.
* @since 0.1.0
*/
Builder setSpanKind(Span.Kind spanKind);
/**
* Sets an explicit start timestamp for the newly created {@code Span}.
*
*
Use this method to specify an explicit start timestamp. If not called, the implementation
* will use the timestamp value at {@link #startSpan()} time, which should be the default case.
*
*
Important this is NOT equivalent with System.nanoTime().
*
* @param startTimestamp the explicit start timestamp of the newly created {@code Span} in nanos
* since epoch.
* @return this.
* @since 0.1.0
*/
Builder setStartTimestamp(long startTimestamp);
/**
* Starts a new {@link Span}.
*
*
Users must manually call {@link Span#end()} to end this {@code Span}.
*
*
Does not install the newly created {@code Span} to the current Context.
*
*
IMPORTANT: This method can be called only once per {@link Builder} instance and as the
* last method called. After this method is called calling any method is undefined behavior.
*
*
Example of usage:
*
*
{@code
* class MyClass {
* private static final Tracer tracer = OpenTelemetry.getTracer();
* void DoWork(Span parent) {
* Span childSpan = tracer.spanBuilder("MyChildSpan")
* .setParent(parent)
* .startSpan();
* childSpan.addEvent("my event");
* try {
* doSomeWork(childSpan); // Manually propagate the new span down the stack.
* } finally {
* // To make sure we end the span even in case of an exception.
* childSpan.end(); // Manually end the span.
* }
* }
* }
* }
*
* @return the newly created {@code Span}.
* @since 0.1.0
*/
Span startSpan();
}
}