public class Tracer extends Object
// Start a new trace or a span within an existing trace representing an operation
ScopedSpan span = tracer.startScopedSpan("encode");
try {
// The span is in "scope" so that downstream code such as loggers can see trace IDs
return encoder.encode();
} catch (RuntimeException | Error e) {
span.error(e); // Unless you handle exceptions, you might not know the operation failed!
throw e;
} finally {
span.finish();
}
When you need more features, or finer control, use the Span type:
// Start a new trace or a span within an existing trace representing an operation
Span span = tracer.nextSpan().name("encode").start();
// Put the span in "scope" so that downstream code such as loggers can see trace IDs
try (SpanInScope ws = tracer.withSpanInScope(span)) {
return encoder.encode();
} catch (RuntimeException | Error e) {
span.error(e); // Unless you handle exceptions, you might not know the operation failed!
throw e;
} finally {
span.finish(); // note the scope is independent of the span. Always finish a span.
}
Both of the above examples report the exact same span on finish!
Span
,
ScopedSpan
,
Propagation
Modifier and Type | Class | Description |
---|---|---|
static class |
Tracer.SpanInScope |
A span remains in the scope it was bound to until close is called.
|
Modifier and Type | Method | Description |
---|---|---|
Span |
currentSpan() |
Returns the current span in scope or null if there isn't one.
|
SpanCustomizer |
currentSpanCustomizer() |
Returns a customizer for current span in scope or noop if there isn't one.
|
Span |
joinSpan(TraceContext context) |
Joining is re-using the same trace and span ids extracted from an incoming RPC request.
|
Span |
newChild(TraceContext parent) |
Explicitly creates a child within an existing trace.
|
Span |
newTrace() |
Explicitly creates a new trace.
|
Span |
nextSpan() |
Returns a new child span if there's a
currentSpan() or a new trace if there isn't. |
Span |
nextSpan(TraceContextOrSamplingFlags extracted) |
This creates a new span based on parameters extracted from an incoming request.
|
ScopedSpan |
startScopedSpan(String name) |
Returns a new child span if there's a
currentSpan() or a new trace if there isn't. |
ScopedSpan |
startScopedSpanWithParent(String name,
TraceContext parent) |
Same as
startScopedSpan(String) , except ignores the current trace context. |
Span |
toSpan(TraceContext context) |
Converts the context to a Span object after decorating it for propagation
|
String |
toString() |
|
Tracer |
withSampler(Sampler sampler) |
Use this to temporarily override the sampler used when starting new traces.
|
Tracer.SpanInScope |
withSpanInScope(Span span) |
Makes the given span the "current span" and returns an object that exits that scope on close.
|
public Tracer withSampler(Sampler sampler)
declarative sampling
.
Simple example:
// Ensures new traces are always started
Tracer tracer = tracing.tracer().withSampler(Sampler.ALWAYS_SAMPLE);
DeclarativeSampler
public Span newTrace()
To implicitly create a new trace, or a span within an existing one, use nextSpan()
.
public final Span joinSpan(TraceContext context)
nextSpan(TraceContextOrSamplingFlags)
is a better choice.
When this incoming context is sampled, we assume this is a shared span, one where the caller and the current tracer report to the same span IDs. If no sampling decision occurred yet, we have exclusive access to this span ID.
Here's an example of conditionally joining a span, depending on if a trace context was extracted from an incoming request.
extracted = extractor.extract(request);
span = contextOrFlags.context() != null
? tracer.joinSpan(contextOrFlags.context())
: tracer.nextSpan(extracted);
Note: When Propagation.Factory.supportsJoin()
is false, this will always
fork a new child via newChild(TraceContext)
.
public Span newChild(TraceContext parent)
To implicitly create a new trace, or a span within an existing one, use nextSpan()
.
public Span nextSpan(TraceContextOrSamplingFlags extracted)
nextSpan()
. If a sampling decision
has not yet been made, one will happen here.
Ex.
extracted = extractor.extract(request);
span = tracer.nextSpan(extracted);
Note: Unlike joinSpan(TraceContext)
, this does not attempt to re-use
extracted span IDs. This means the extracted context (if any) is the parent of the span
returned.
Note: If a context could be extracted from the input, that trace is resumed, not
whatever the currentSpan()
was. Make sure you re-apply withSpanInScope(Span)
so that data is written to the correct trace.
public Span toSpan(TraceContext context)
public Tracer.SpanInScope withSpanInScope(@Nullable Span span)
currentSpan()
and currentSpanCustomizer()
will affect this span
until the return value is closed.
The most convenient way to use this method is via the try-with-resources idiom. Ex.
// Assume a framework interceptor uses this method to set the inbound span as current
try (SpanInScope ws = tracer.withSpanInScope(span)) {
return inboundRequest.invoke();
// note: try-with-resources closes the scope *before* the catch block
} catch (RuntimeException | Error e) {
span.error(e);
throw e;
} finally {
span.finish();
}
// An unrelated framework interceptor can now lookup the correct parent for outbound requests
Span parent = tracer.currentSpan()
Span span = tracer.nextSpan().name("outbound").start(); // parent is implicitly looked up
try (SpanInScope ws = tracer.withSpanInScope(span)) {
return outboundRequest.invoke();
// note: try-with-resources closes the scope *before* the catch block
} catch (RuntimeException | Error e) {
span.error(e);
throw e;
} finally {
span.finish();
}
When tracing in-process commands, prefer startScopedSpan(String)
which scopes by
default.
Note: While downstream code might affect the span, calling this method, and calling close on the result have no effect on the input. For example, calling close on the result does not finish the span. Not only is it safe to call close, you must call close to end the scope, or risk leaking resources associated with the scope.
span
- span to place into scope or null to clear the scopepublic SpanCustomizer currentSpanCustomizer()
Unlike CurrentSpanCustomizer
, this represents a single span. Accordingly, this
reference should not be saved as a field. That said, it is more efficient to save this result
as a method-local variable vs repeated calls.
@Nullable public Span currentSpan()
When entering user code, prefer currentSpanCustomizer()
as it is a stable type and
will never return null.
public Span nextSpan()
currentSpan()
or a new trace if there isn't.
Prefer startScopedSpan(String)
if you are tracing a synchronous function or code
block.
public ScopedSpan startScopedSpan(String name)
currentSpan()
or a new trace if there isn't. The
result is the "current span" until ScopedSpan.finish()
is called.
Here's an example:
ScopedSpan span = tracer.startScopedSpan("encode");
try {
// The span is in "scope" so that downstream code such as loggers can see trace IDs
return encoder.encode();
} catch (RuntimeException | Error e) {
span.error(e); // Unless you handle exceptions, you might not know the operation failed!
throw e;
} finally {
span.finish();
}
public ScopedSpan startScopedSpanWithParent(String name, @Nullable TraceContext parent)
startScopedSpan(String)
, except ignores the current trace context.
Use this when you are creating a scoped span in a method block where the parent was created. You can also use this to force a new trace by passing null parent.
Copyright © 2018 OpenZipkin. All rights reserved.