com.aliyun.openservices.shade.io.opentelemetry.api.trace.SpanBuilder Maven / Gradle / Ivy
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package com.aliyun.openservices.shade.com.aliyun.openservices.shade.io.opentelemetry.api.trace;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.aliyun.openservices.shade.com.aliyun.openservices.shade.io.opentelemetry.api.common.AttributeKey;
import com.aliyun.openservices.shade.com.aliyun.openservices.shade.io.opentelemetry.api.common.Attributes;
import com.aliyun.openservices.shade.com.aliyun.openservices.shade.io.opentelemetry.context.Context;
import java.time.Instant;
import java.util.concurrent.TimeUnit;
/**
* {@link SpanBuilder} 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 final Tracer tracer;
*
* MyClass(OpenTelemetry openTelemetry) {
* tracer = openTelemetry.getTracer("com.anyco.rpc");
* }
*
* void doWork() {
* // Create a Span as a child of the current Span.
* Span span = tracer.spanBuilder("MyChildSpan").startSpan();
* try (Scope ss = span.makeCurrent()) {
* span.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 final Tracer tracer;
* private Span mySpan;
*
* public MyRpcInterceptor(OpenTelemetry openTelemetry) {
* tracer = openTelemetry.getTracer("com.example.rpc");
* }
*
* public void onRequest(String rpcName, Metadata metadata) {
* // Create a Span as a child of the remote Span.
* mySpan = tracer.spanBuilder(rpcName)
* .setParent(extractContextFromMetadata(metadata)).startSpan();
* }
*
* public void onExecuteHandler(ServerCallHandler serverCallHandler) {
* try (Scope ws = mySpan.makeCurrent()) {
* Span.current().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(StatusCode.ERROR);
* 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 final Tracer tracer;
*
* MyClass(OpenTelemetry openTelemetry) {
* tracer = openTelemetry.getTracer("com.example.rpc");
* }
*
* void doWork(Span parent) {
* Span childSpan = tracer.spanBuilder("MyChildSpan")
* .setParent(Context.current().with(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.
* }
* }
* }
* }
*
* see {@link SpanBuilder#startSpan} for usage examples.
*/
public interface SpanBuilder {
/**
* Sets the parent to use from the specified {@code Context}. If not set, the value of {@code
* Span.current()} 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.
*/
SpanBuilder setParent(Context context);
/**
* Sets the option to become a root {@code Span} for a new trace. If not set, the value of {@code
* Span.current()} at {@link #startSpan()} time will be used as parent.
*
*
Observe that any previously set parent will be discarded.
*
* @return this.
*/
SpanBuilder setNoParent();
/**
* Adds a 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.
*
*
Implementations may ignore calls with an {@linkplain SpanContext#isValid() invalid span
* context}.
*
* @param spanContext the context of the linked {@code Span}.
* @return this.
*/
SpanBuilder addLink(SpanContext spanContext);
/**
* Adds a 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.
*
*
Implementations may ignore calls with an {@linkplain SpanContext#isValid() invalid span
* context}.
*
* @param spanContext the context of the linked {@code Span}.
* @param attributes the attributes of the {@code Link}.
* @return this.
*/
SpanBuilder addLink(SpanContext spanContext, Attributes attributes);
/**
* Sets an attribute to the newly created {@code Span}. If {@code SpanBuilder} 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 behavior is undefined, and hence
* strongly discouraged.
*
*
Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
* pre-allocate your keys, if possible.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
*/
SpanBuilder setAttribute(String key, String value);
/**
* Sets an attribute to the newly created {@code Span}. If {@code SpanBuilder} previously
* contained a mapping for the key, the old value is replaced by the specified value.
*
*
Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
* pre-allocate your keys, if possible.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
*/
SpanBuilder setAttribute(String key, long value);
/**
* Sets an attribute to the newly created {@code Span}. If {@code SpanBuilder} previously
* contained a mapping for the key, the old value is replaced by the specified value.
*
*
Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
* pre-allocate your keys, if possible.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
*/
SpanBuilder setAttribute(String key, double value);
/**
* Sets an attribute to the newly created {@code Span}. If {@code SpanBuilder} previously
* contained a mapping for the key, the old value is replaced by the specified value.
*
*
Note: It is strongly recommended to use {@link #setAttribute(AttributeKey, Object)}, and
* pre-allocate your keys, if possible.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
*/
SpanBuilder setAttribute(String key, boolean value);
/**
* Sets an attribute to the newly created {@code Span}. If {@code SpanBuilder} previously
* contained a mapping for the key, the old value is replaced by the specified value.
*
*
Note: the behavior of null values is undefined, and hence strongly discouraged.
*
* @param key the key for this attribute.
* @param value the value for this attribute.
* @return this.
*/
SpanBuilder setAttribute(AttributeKey key, T value);
/**
* Sets attributes to the {@link SpanBuilder}. If the {@link SpanBuilder} previously contained a
* mapping for any of the keys, the old values are replaced by the specified values.
*
* @param attributes the attributes
* @return this.
* @since 1.2.0
*/
@SuppressWarnings("unchecked")
default SpanBuilder setAllAttributes(Attributes attributes) {
if (attributes == null || attributes.isEmpty()) {
return this;
}
attributes.forEach(
(attributeKey, value) -> setAttribute((AttributeKey