/** Returns a copy of this Trace which can be independently mutated. */ Trace deepCopy() { return new Trace(new ArrayDeque<>(stack), isObservable, traceId); } }
/** Returns an independent copy of this thread's {@link Trace}. */ static Trace copyTrace() { return currentTrace.get().deepCopy(); }
/** Returns the globally unique identifier for this thread's trace. */ public static String getTraceId() { return currentTrace.get().getTraceId(); }
private static OpenSpan startSpanInternal(String operation, SpanType type) { OpenSpan.Builder spanBuilder = OpenSpan.builder() .operation(operation) .spanId(Tracers.randomId()) .type(type); Optional<OpenSpan> prevState = currentTrace.get().top(); if (prevState.isPresent()) { spanBuilder.parentSpanId(prevState.get().getSpanId()); } OpenSpan span = spanBuilder.build(); currentTrace.get().push(span); return span; }
/** * Opens a new span for this thread's call trace, labeled with the provided operation and parent span. Only allowed * when the current trace is empty. */ public static OpenSpan startSpan(String operation, String parentSpanId, SpanType type) { Preconditions.checkState(currentTrace.get().isEmpty(), "Cannot start a span with explicit parent if the current thread's trace is non-empty"); Preconditions.checkArgument(parentSpanId != null && !parentSpanId.isEmpty(), "parentTraceId must be non-empty: %s", parentSpanId); OpenSpan span = OpenSpan.builder() .spanId(Tracers.randomId()) .operation(operation) .parentSpanId(parentSpanId) .type(type) .build(); currentTrace.get().push(span); return span; }
/** * True iff the spans of this thread's trace are to be observed by {@link SpanObserver span obververs} upon {@link * Tracer#completeSpan span completion}. */ public static boolean isTraceObservable() { return currentTrace.get().isObservable(); }
private static Optional<OpenSpan> popCurrentSpan() { return currentTrace.get().pop(); }
private static OpenSpan startSpanInternal(String operation, SpanType type) { OpenSpan.Builder spanBuilder = OpenSpan.builder() .operation(operation) .spanId(Tracers.randomId()) .type(type); Optional<OpenSpan> prevState = currentTrace.get().top(); if (prevState.isPresent()) { spanBuilder.parentSpanId(prevState.get().getSpanId()); } OpenSpan span = spanBuilder.build(); currentTrace.get().push(span); return span; }
/** * Opens a new span for this thread's call trace, labeled with the provided operation and parent span. Only allowed * when the current trace is empty. */ public static OpenSpan startSpan(String operation, String parentSpanId, SpanType type) { Preconditions.checkState(currentTrace.get().isEmpty(), "Cannot start a span with explicit parent if the current thread's trace is non-empty"); Preconditions.checkArgument(parentSpanId != null && !parentSpanId.isEmpty(), "parentTraceId must be non-empty: %s", parentSpanId); OpenSpan span = OpenSpan.builder() .spanId(Tracers.randomId()) .operation(operation) .parentSpanId(parentSpanId) .type(type) .build(); currentTrace.get().push(span); return span; }
/** * True iff the spans of this thread's trace are to be observed by {@link SpanObserver span obververs} upon {@link * Tracer#completeSpan span completion}. */ public static boolean isTraceObservable() { return currentTrace.get().isObservable(); }
private static Optional<OpenSpan> popCurrentSpan() { return currentTrace.get().pop(); }
/** * Like {@link #fastCompleteSpan()}, but adds {@code metadata} to the current span being completed. */ public static void fastCompleteSpan(Map<String, String> metadata) { popCurrentSpan() .filter(openSpan -> currentTrace.get().isObservable()) .map(openSpan -> toSpan(openSpan, metadata)) .ifPresent(Tracer::notifyObservers); }
/** Returns a copy of this Trace which can be independently mutated. */ Trace deepCopy() { return new Trace(new ArrayDeque<>(stack), isObservable, traceId); } }
/** Returns the globally unique identifier for this thread's trace. */ public static String getTraceId() { return currentTrace.get().getTraceId(); }
/** Returns an independent copy of this thread's {@link Trace}. */ static Trace copyTrace() { return currentTrace.get().deepCopy(); }
/** * Like {@link #fastCompleteSpan()}, but adds {@code metadata} to the current span being completed. */ public static void fastCompleteSpan(Map<String, String> metadata) { popCurrentSpan() .filter(openSpan -> currentTrace.get().isObservable()) .map(openSpan -> toSpan(openSpan, metadata)) .ifPresent(Tracer::notifyObservers); }
/** * Creates a new trace, but does not set it as the current trace. 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. */ private static Trace createTrace(Optional<Boolean> isObservable, String traceId) { Preconditions.checkArgument(traceId != null && !traceId.isEmpty(), "traceId must be non-empty: %s", traceId); boolean observable = isObservable.orElseGet(sampler::sample); return new Trace(observable, traceId); }
/** * Sets the thread-local trace. Considered an internal API used only for propagating the trace state across * threads. */ static void setTrace(Trace trace) { currentTrace.set(trace); // Give SLF4J appenders access to the trace id MDC.put(Tracers.TRACE_ID_KEY, trace.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; }
/** * Creates a new trace, but does not set it as the current trace. 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. */ private static Trace createTrace(Optional<Boolean> isObservable, String traceId) { Preconditions.checkArgument(traceId != null && !traceId.isEmpty(), "traceId must be non-empty: %s", traceId); boolean observable = isObservable.orElseGet(sampler::sample); return new Trace(observable, traceId); }