/** * Completes and returns the current span (if it exists) and notifies all {@link #observers subscribers} about the * completed span. */ public static Optional<Span> completeSpan() { return completeSpan(Collections.emptyMap()); }
/** * Opens a new {@link SpanType#LOCAL LOCAL} span for this thread's call trace, labeled with the provided operation. */ public static CloseableTracer startSpan(String operation) { Tracer.startSpan(operation); return INSTANCE; }
/** * The inverse of {@link #subscribe}: removes the observer registered for the given name. Returns the removed * observer if it existed, or null otherwise. */ public static synchronized SpanObserver unsubscribe(String name) { SpanObserver removedObserver = observers.remove(name); computeObserversList(); return removedObserver; }
/** * Initializes the current thread's trace, erasing any previously accrued open spans. The new trace is {@link * Trace#isObservable observable} iff the given flag is true, or, iff {@code isObservable} is absent, if the {@link * #setSampler configured sampler} returns true. */ public static void initTrace(Optional<Boolean> isObservable, String traceId) { setTrace(createTrace(isObservable, traceId)); }
/** * Runs the given callable with the current trace at * the time of construction of this {@link DeferredTracer}. */ public <T, E extends Throwable> T withTrace(ThrowingCallable<T, E> inner) throws E { Trace originalTrace = Tracer.copyTrace(); Tracer.setTrace(trace); try { return inner.call(); } finally { Tracer.setTrace(originalTrace); } } }
@Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); String spanName = request.method(); String httpRemotingPath = request.header(PATH_TEMPLATE_HEADER); if (httpRemotingPath != null) { spanName = httpRemotingPath; request = request.newBuilder().removeHeader(PATH_TEMPLATE_HEADER).build(); } OpenSpan span = Tracer.startSpan(spanName, SpanType.CLIENT_OUTGOING); Request.Builder tracedRequest = request.newBuilder() .addHeader(TraceHttpHeaders.TRACE_ID, Tracer.getTraceId()) .addHeader(TraceHttpHeaders.SPAN_ID, span.getSpanId()) .addHeader(TraceHttpHeaders.IS_SAMPLED, Tracer.isTraceObservable() ? "1" : "0"); if (span.getParentSpanId().isPresent()) { tracedRequest.header(TraceHttpHeaders.PARENT_SPAN_ID, span.getParentSpanId().get()); } Response response; try { response = chain.proceed(tracedRequest.build()); } finally { Tracer.completeSpan(); } return response; }
/** * Wraps the given {@link Runnable} such that it creates a fresh {@link Trace tracing state with the given traceId} * for its execution. That is, the trace during its {@link Runnable#run() execution} will use the traceId provided * instead of any trace already set on the thread used to execute the runnable. Each execution of the runnable * will use a new {@link Trace tracing state} with the same given traceId. */ public static Runnable wrapWithAlternateTraceId(String traceId, Runnable delegate) { return () -> { // clear the existing trace and keep it around for restoration when we're done Trace originalTrace = Tracer.getAndClearTrace(); try { Tracer.initTrace(Optional.empty(), traceId); delegate.run(); } finally { // restore the trace Tracer.setTrace(originalTrace); } }; }
@Override public void filter(ContainerRequestContext requestContext) throws IOException { String path = Optional.ofNullable(uriInfo) .map(ExtendedUriInfo::getMatchedModelResource) .map(Resource::getPath) .orElse("(unknown)"); String operation = requestContext.getMethod() + " " + path; // The following strings are all nullable String traceId = requestContext.getHeaderString(TraceHttpHeaders.TRACE_ID); String spanId = requestContext.getHeaderString(TraceHttpHeaders.SPAN_ID); // Set up thread-local span that inherits state from HTTP headers if (Strings.isNullOrEmpty(traceId)) { // HTTP request did not indicate a trace; initialize trace state and create a span. Tracer.initTrace(hasSampledHeader(requestContext), Tracers.randomId()); Tracer.startSpan(operation, SpanType.SERVER_INCOMING); } else { Tracer.initTrace(hasSampledHeader(requestContext), traceId); if (spanId == null) { Tracer.startSpan(operation, SpanType.SERVER_INCOMING); } else { // caller's span is this span's parent. Tracer.startSpan(operation, spanId, SpanType.SERVER_INCOMING); } } // Give asynchronous downstream handlers access to the trace id requestContext.setProperty("com.palantir.conjure.java.traceId", Tracer.getTraceId()); }
/** * Like {@link #completeSpan()}, but adds {@code metadata} to the current span being completed. */ public static Optional<Span> completeSpan(Map<String, String> metadata) { Optional<Span> maybeSpan = popCurrentSpan() .map(openSpan -> toSpan(openSpan, metadata)); // Notify subscribers iff trace is observable maybeSpan.ifPresent(span -> { if (currentTrace.get().isObservable()) { notifyObservers(span); } }); return maybeSpan; }
private static Span toSpan(OpenSpan openSpan, Map<String, String> metadata) { return Span.builder() .traceId(getTraceId()) .spanId(openSpan.getSpanId()) .type(openSpan.type()) .parentSpanId(openSpan.getParentSpanId()) .operation(openSpan.getOperation()) .startTimeMicroSeconds(openSpan.getStartTimeMicroSeconds()) .durationNanoSeconds(System.nanoTime() - openSpan.getStartClockNanoSeconds()) .putAllMetadata(metadata) .build(); }
@Override public void close() { Tracer.fastCompleteSpan(); } }
public DeferredTracer() { this.trace = Tracer.copyTrace(); }
/** * Wraps the given {@link Runnable} such that it creates a fresh {@link Trace tracing state with the given traceId} * for its execution. That is, the trace during its {@link Runnable#run() execution} will use the traceId provided * instead of any trace already set on the thread used to execute the runnable. Each execution of the runnable * will use a new {@link Trace tracing state} with the same given traceId. */ public static Runnable wrapWithAlternateTraceId(String traceId, Runnable delegate) { return () -> { // clear the existing trace and keep it around for restoration when we're done Trace originalTrace = Tracer.getAndClearTrace(); try { Tracer.initTrace(Optional.empty(), traceId); delegate.run(); } finally { // restore the trace Tracer.setTrace(originalTrace); } }; }
/** * Like {@link #completeSpan()}, but adds {@code metadata} to the current span being completed. */ public static Optional<Span> completeSpan(Map<String, String> metadata) { Optional<Span> maybeSpan = popCurrentSpan() .map(openSpan -> toSpan(openSpan, metadata)); // Notify subscribers iff trace is observable maybeSpan.ifPresent(span -> { if (currentTrace.get().isObservable()) { notifyObservers(span); } }); return maybeSpan; }
/** * Initializes the current thread's trace, erasing any previously accrued open spans. The new trace is {@link * Trace#isObservable observable} iff the given flag is true, or, iff {@code isObservable} is absent, if the {@link * #setSampler configured sampler} returns true. */ public static void initTrace(Optional<Boolean> isObservable, String traceId) { setTrace(createTrace(isObservable, traceId)); }
private static Span toSpan(OpenSpan openSpan, Map<String, String> metadata) { return Span.builder() .traceId(getTraceId()) .spanId(openSpan.getSpanId()) .type(openSpan.type()) .parentSpanId(openSpan.getParentSpanId()) .operation(openSpan.getOperation()) .startTimeMicroSeconds(openSpan.getStartTimeMicroSeconds()) .durationNanoSeconds(System.nanoTime() - openSpan.getStartClockNanoSeconds()) .putAllMetadata(metadata) .build(); }
/** * Runs the given callable with the current trace at * the time of construction of this {@link DeferredTracer}. */ public <T, E extends Throwable> T withTrace(ThrowingCallable<T, E> inner) throws E { Trace originalTrace = Tracer.copyTrace(); Tracer.setTrace(trace); try { return inner.call(); } finally { Tracer.setTrace(originalTrace); } } }
@Override public void close() { Tracer.fastCompleteSpan(); } }
public DeferredTracer() { this.trace = Tracer.copyTrace(); }
/** * Like {@link #wrapWithNewTrace(Callable)}, but for Runnables. */ public static Runnable wrapWithNewTrace(Runnable delegate) { return () -> { // clear the existing trace and keep it around for restoration when we're done Trace originalTrace = Tracer.getAndClearTrace(); try { Tracer.initTrace(Optional.empty(), Tracers.randomId()); delegate.run(); } finally { // restore the trace Tracer.setTrace(originalTrace); } }; }