public class Tracer extends Object
This class is meant to be used in conjunction with SpanBuilderFactory
, which is capable of constructing the Span
arguments that must be passed into methods like startTrace(Span)
.
TracerSpan
. This is done to clarify that such instances are now managed by
the Tracer and user code should no longer interact with the argument. in fact, TracerSpans generally act as
decorators around the Span arguments.
In any case, most users of the API will want to simply up-cast to Span for cleaner code.
On the other hand, where a method returns just Span, expect the instance to longer be managed by the tracer.
Because of the thread-local nature of the Tracer, TracerSpans are meant to be used on the thread they are created on. They directly interact with the Tracer's thread-local context.
There are guards and logging in place to deal with situations where this may be violated.
You can use the trace[Callable/Runnable/...]
methods in this class to wrap various functional
interfaces and automatically manage propagation when these get passed to, for instance, a
CompletableFuture
or some Executor
.
You can also use startDetachedChildSpan(String)
to create a child span that you can pass on to another
thread (assuming you safely establish a happens-before relation), where you can choose to handle them
manually or start a new trace
.
See the javadoc of each of the mentioned methods for more details.
Constructor | Description |
---|---|
Tracer(SpanBuilderFactory factory) |
Creates a tracer.
|
Tracer(SpanBuilderFactory factory,
TracingContext context) |
Modifier and Type | Method | Description |
---|---|---|
void |
endTrace() |
This ends the trace currently active on this thread and submits the "root" Span to Honeycomb.
|
TracerSpan |
getActiveSpan() |
Returns the span that is currently active on this thread - the one that is top of the stack.
|
Span |
popSpan(Span spanToPop) |
Detaches the span identified by the argument's spanId from the thread-local context (i.e.
|
TracerSpan |
pushSpan(Span span) |
Attaches the Span to the tracer's thread-local context (i.e.
|
Span |
startChildSpan(String childSpanName) |
Starts and returns a new span as the child of the previous span.
|
Span |
startDetachedChildSpan(String childSpanName) |
Starts and returns a new span as the child of the previous span, but without being attached to this Tracer's
thread-local context.
|
TracerSpan |
startTrace(Span span) |
Starts a trace by attaching the provided Span to the Tracer's thread-local context as the new "root".
|
<T> Callable<T> |
traceCallable(String childSpanName,
Callable<? extends T> callable) |
Wraps the supplied Callable so that the currently active trace can be continued within it even if executed
asynchronously in a different thread.
|
<T> Consumer<T> |
traceConsumer(String childSpanName,
Consumer<? super T> consumer) |
Wraps the supplied Consumer so that the currently active trace can be continued within it even if executed
asynchronously in a different thread.
|
<T,R> Function<T,R> |
traceFunction(String childSpanName,
Function<? super T,? extends R> function) |
Wraps the supplied Function so that the currently active trace can be continued within it even if executed
asynchronously in a different thread.
|
Runnable |
traceRunnable(String childSpanName,
Runnable runnable) |
Wraps the supplied Runnable so that the currently active trace can be continued within it even if executed
asynchronously in a different thread.
|
<T> Supplier<T> |
traceSupplier(String childSpanName,
Supplier<? extends T> supplier) |
Wraps the supplied Supplier so that the currently active trace can be continued within it even if executed
asynchronously in a different thread.
|
public Tracer(SpanBuilderFactory factory)
Tracing
's factory methods.factory
- used to construct spans internally.public Tracer(SpanBuilderFactory factory, TracingContext context)
public TracerSpan startTrace(Span span)
TracerSpan
.
See the Tracer's class-level Javadoc for details.
The trace should eventually be ended by calling endTrace()
or Span.close()
on the "root" Span.
Note that if any Spans are still attached to this Tracer, when this method is called then they will be cleared and submitted to Honeycomb, whilst also logging a warning that trace has been improperly ended.
span
- to be attached to this tracer - must not be null.IllegalArgumentException
- if argument is null.SpanBuilderFactory
public TracerSpan pushSpan(Span span)
It is subsequently wrapped and returned as a managed TracerSpan
.
See the Tracer's class-level Javadoc for details.
This differs to startTrace(Span)
in that it does not clear existing context, but rather treats the
added Span as the child of the previous active Span (i.e. you are pushing it onto a stack).
Note that no checks are performed for whether the new Span's parentSpanId
or traceId
match with the previous Span. This technically allows the nesting of traces without having to clear the previous
trace.
span
- to attach to the Tracer.IllegalArgumentException
- if the argument is null.public Span popSpan(Span spanToPop)
Since the returned Span is no longer managed by this Tracer you must explicitly call Span.close()
on it
in order to submit it to Honeycomb.
If the Span had a parent, then the parent span will become the new active span (i.e. you are popping the active span off of a stack).
spanToPop
- used to find the correct span.IllegalArgumentException
- if the argument is null.public void endTrace()
startTrace(Span)
).
If children of the "root" Span are still active, because Span.close() has not been properly called on them, then the tracer will perform cleanup of the active children regardless. Note that in that case span durations may be skewed.
public TracerSpan getActiveSpan()
SpanBuilderFactory
.
if (underAttack) { final Span currentSpan = tracer.getActiveSpan() .addField("alert-message", "We are under attack!") .addField("alert-level", "red"); }
public Span startChildSpan(String childSpanName)
This means the child becomes the new active span (see getActiveSpan()
on this thread.
The old active span (i.e the "parent span") is linked to the child via the Parent ID and via reference.
When Span.close() closing the child} the parent will be reset to being the active span.
Because of the parent and child being linked by reference, the child's lifetime is tied and limited to that of the parent.
// try-with-resources statement automatically closes the span try (Span childSpan = tracer.startChildSpan("http-call")) { childSpan.addField("http-url", url); return httpClient.get(url); }
childSpanName
- to use as the name of the new span - must not be empty.IllegalArgumentException
- if the argument is null or empty.public Span startDetachedChildSpan(String childSpanName)
parentSpanId
only.
This is for advanced use cases when, for instance, you need to track asynchronous computations
and call Span.markStart()
and Span.close()
at specific points.
The trace*()
methods might be useful if you need to trace lambdas/functional interfaces.
If your computation does not cross thread boundaries startChildSpan(String)
may be more convenient.
final Span httpServiceSpan = tracer.startDetachedChildSpan("http-call"); httpServiceSpan.addField("http-url", url); CompletableFuture .supplyAsync(()->
{ // on a different thread, so using the tracer won't work here httpServiceSpan.markStart(); // start measuring time when thread actually starts processing return httpClient.get(url); }) .thenApplyAsync(this::convertResponse) .thenApplyAsync(this::handleResponse) // add exception message if something went wrong .exceptionally(e->
httpServiceSpan.addField("error-message", e.getMessage())) .thenRun(httpServiceSpan::close); // close span and submit to Honeycomb
childSpanName
- to use as the name of the new span - must not be empty.IllegalArgumentException
- if the argument is null or empty.public Runnable traceRunnable(String childSpanName, Runnable runnable)
If the returned Runnable is executed on another thread it initializes the tracer's thread-local context for that thread, while leaving the current thread's context unaffected.
If run on the same thread while the current trace is still active this will simply start a new child span within the current thread's context.
CompletableFuture.runAsync(tracer.traceRunnable("http-call", ()->
httpClient.get(url)));
childSpanName
- name of the child Span created for the runnable - must not be null or empty.runnable
- to wrap - must not be null.IllegalArgumentException
- if arguments are null or empty.public <T> Callable<T> traceCallable(String childSpanName, Callable<? extends T> callable)
If the returned Callable is executed on another thread it initializes the tracer's thread-local context for that thread, while leaving the current thread's context unaffected.
If run on the same thread while the current trace is still active this will simply start a new child span within the current thread's context.
Future<Response>
responseFuture = executor.submit(tracer.traceCallable("http-call", ()->
httpClient.get(url)));
T
- the return type.childSpanName
- name of the child Span created for the Callable - must not be null or empty.callable
- to wrap - must not be null.IllegalArgumentException
- if arguments are null or empty.public <T> Supplier<T> traceSupplier(String childSpanName, Supplier<? extends T> supplier)
If the returned Supplier is executed on another thread it initializes the tracer's thread-local context for that thread, while leaving the current thread's context unaffected.
If run on the same thread while the current trace is still active this will simply start a new child span within the current thread's context.
CompletableFuture.supplyAsync(tracer.traceSupplier("http-call", ()->
httpClient.get(url)))
T
- the return type.childSpanName
- name of the child Span created for the Supplier - must not be null or empty.supplier
- to wrap - must not be null.IllegalArgumentException
- if arguments are null or empty.public <T,R> Function<T,R> traceFunction(String childSpanName, Function<? super T,? extends R> function)
If the returned Function is executed on another thread it initializes the tracer's thread-local context for that thread, while leaving the current thread's context unaffected.
If run on the same thread while the current trace is still active this will simply start a new child span within the current thread's context.
completableFuture.thenApply(tracer.traceFunction("handle-response", Converter::convertResponse));
T
- the parameter type.R
- the return type.childSpanName
- name of the child Span created for the Function - must not be null or empty.function
- to wrap - must not be null.IllegalArgumentException
- if arguments are null or empty.public <T> Consumer<T> traceConsumer(String childSpanName, Consumer<? super T> consumer)
If the returned Consumer is executed on another thread it initializes the tracer's thread-local context for that thread, while leaving the current thread's context unaffected.
If run on the same thread while the current trace is still active this will simply start a new child span within the current thread's context.
completableFuture.thenAccept(
tracer.traceConsumer("handle-response", (response)->
handleResponse(response)));
T
- the return type.childSpanName
- name of the child Span created for the Consumer - must not be null or empty.consumer
- to wrap - must not be null.IllegalArgumentException
- if arguments are null or empty.Copyright © 2019–2020 Honeycomb. All rights reserved.