public abstract class SpanBuilder extends Object
SpanBuilder
is used to construct 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:
class MyClass {
private static final Tracer tracer = Tracing.getTracer();
void doWork {
// Create a Span as a child of the current Span.
try (Scope ss = tracer.spanBuilder("MyChildSpan").startScopedSpan()) {
tracer.getCurrentSpan().addAnnotation("my annotation");
doSomeWork(); // Here the new span is in the current Context, so it can be used
// implicitly anywhere down the stack.
}
}
}
There might be cases where you do not perform all the work inside one static scope and the Context is automatically propagated:
class MyRpcServerInterceptorListener implements RpcServerInterceptor.Listener {
private static final Tracer tracer = Tracing.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.spanBuilderWithRemoteParent(
getTraceContextFromMetadata(metadata), rpcName).startSpan();
}
public void onExecuteHandler(ServerCallHandler serverCallHandler) {
try (Scope ws = tracer.withSpan(mySpan)) {
tracer.getCurrentSpan().addAnnotation("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.end(EndSpanOptions.builder().setStatus(Status.CANCELLED));
}
// 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.end(EndSpanOptions.builder().setStatus(rpcStatusToCanonicalTraceStatus(status));
}
}
This is a simple example where all the work is being done within a single scope and the Context is manually propagated:
class MyClass {
private static final Tracer tracer = Tracing.getTracer();
void DoWork(Span parent) {
Span childSpan = tracer.spanBuilderWithExplicitParent("MyChildSpan", parent).startSpan();
childSpan.addAnnotation("my annotation");
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 startSpan()
and startScopedSpan()
for usage examples.
Constructor and Description |
---|
SpanBuilder() |
Modifier and Type | Method and Description |
---|---|
abstract SpanBuilder |
setParentLinks(List<Span> parentLinks)
Sets the
List of parent links. |
abstract SpanBuilder |
setRecordEvents(boolean recordEvents)
Sets the option
Span.Options.RECORD_EVENTS for the newly created Span . |
abstract SpanBuilder |
setSampler(Sampler sampler)
Sets the
Sampler to use. |
SpanBuilder |
setSpanKind(Span.Kind spanKind)
Sets the
Span.Kind for the newly created Span . |
Scope |
startScopedSpan()
Starts a new span and sets it as the
current span . |
abstract Span |
startSpan()
Starts a new
Span . |
<V> V |
startSpanAndCall(Callable<V> callable)
Starts a new span and calls the given
Callable with the newly created Span as
the current Span , and ends the Span after the Callable is called. |
void |
startSpanAndRun(Runnable runnable)
Starts a new span and runs the given
Runnable with the newly created Span as
the current Span , and ends the Span after the Runnable is run. |
public abstract SpanBuilder setSampler(Sampler sampler)
Sampler
to use. If not set, the implementation will provide a default.sampler
- the Sampler
to use when determining sampling for a Span
.public abstract SpanBuilder setParentLinks(List<Span> parentLinks)
List
of parent links. Links are used to link Span
s in different
traces. Used (for example) in batching operations, where a single batch handler processes
multiple requests from different traces.parentLinks
- new links to be added.NullPointerException
- if parentLinks
is null
.public abstract SpanBuilder setRecordEvents(boolean recordEvents)
Span.Options.RECORD_EVENTS
for the newly created Span
. If not
called, the implementation will provide a default.recordEvents
- new value determining if this Span
should have events recorded.public SpanBuilder setSpanKind(@Nullable Span.Kind spanKind)
Span.Kind
for the newly created Span
. If not called, the
implementation will provide a default.spanKind
- the kind of the newly created Span
.public abstract Span startSpan()
Span
.
Users must manually call Span.end()
or Span.end(EndSpanOptions)
to
end this Span
.
Does not install the newly created Span
to the current Context.
Example of usage:
class MyClass {
private static final Tracer tracer = Tracing.getTracer();
void DoWork(Span parent) {
Span childSpan = tracer.spanBuilderWithExplicitParent("MyChildSpan", parent).startSpan();
childSpan.addAnnotation("my annotation");
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.
}
}
}
Span
.@MustBeClosed public final Scope startScopedSpan()
current span
.
Enters the scope of code where the newly created Span
is in the current Context, and
returns an object that represents that scope. When the returned object is closed, the scope is
exited, the previous Context is restored, and the newly created Span
is ended using
Span.end(io.opencensus.trace.EndSpanOptions)
.
Supports try-with-resource idiom.
Example of usage:
class MyClass {
private static final Tracer tracer = Tracing.getTracer();
void doWork {
// Create a Span as a child of the current Span.
try (Scope ss = tracer.spanBuilder("MyChildSpan").startScopedSpan()) {
tracer.getCurrentSpan().addAnnotation("my annotation");
doSomeWork(); // Here the new span is in the current Context, so it can be used
// implicitly anywhere down the stack. Anytime in this closure the span
// can be accessed via tracer.getCurrentSpan().
}
}
}
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed (the
Span
is ended and removed from the Context) regardless of whether the try statement
completes normally or abruptly.
Example of usage prior to Java SE7:
class MyClass {
private static Tracer tracer = Tracing.getTracer();
void doWork {
// Create a Span as a child of the current Span.
Scope ss = tracer.spanBuilder("MyChildSpan").startScopedSpan();
try {
tracer.getCurrentSpan().addAnnotation("my annotation");
doSomeWork(); // Here the new span is in the current Context, so it can be used
// implicitly anywhere down the stack. Anytime in this closure the span
// can be accessed via tracer.getCurrentSpan().
} finally {
ss.close();
}
}
}
WARNING: The try-with-resources feature to auto-close spans as described above can sound
very tempting due to its convenience, but it comes with an important and easy-to-miss
trade-off: the span will be closed before any catch
or finally
blocks get a
chance to execute. So if you need to catch any exceptions and log information about them (for
example), then you do not want to use the try-with-resources shortcut because that logging will
not be tagged with the span info of the span it logically falls under, and if you try to
retrieve Tracer.getCurrentSpan()
then you'll either get the parent span if one exists
or BlankSpan
if there was no parent span. This can be confusing and seem
counter-intuitive, but it's the way try-with-resources works.
Span
will be set to the
current Context.public final void startSpanAndRun(Runnable runnable)
Runnable
with the newly created Span
as
the current Span
, and ends the Span
after the Runnable
is run.
Any error will end up as a Status.UNKNOWN
.
tracer.spanBuilder("MyRunnableSpan").startSpanAndRun(myRunnable);
It is equivalent with the following code:
Span span = tracer.spanBuilder("MyRunnableSpan").startSpan();
Runnable newRunnable = tracer.withSpan(span, myRunnable);
try {
newRunnable.run();
} finally {
span.end();
}
runnable
- the Runnable
to run in the Span
.public final <V> V startSpanAndCall(Callable<V> callable) throws Exception
Callable
with the newly created Span
as
the current Span
, and ends the Span
after the Callable
is called.
Any error will end up as a Status.UNKNOWN
.
MyResult myResult = tracer.spanBuilder("MyCallableSpan").startSpanAndCall(myCallable);
It is equivalent with the following code:
Span span = tracer.spanBuilder("MyCallableSpan").startSpan();
Callable<MyResult>
newCallable = tracer.withSpan(span, myCallable);
MyResult myResult = null;
try {
myResult = newCallable.call();
} finally {
span.end();
}
);
callable
- the Callable
to run in the Span
.Exception