@Override public List<List<Span>> getTracesByIds(List<Long> traceIds) { tracer.startNewSpan(component, "get-traces-by-ids"); try { return delegate.getTracesByIds(traceIds); } finally { tracer.finishSpan(); } }
@Override public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof LocalTracer) { LocalTracer that = (LocalTracer) o; return (this.recorder.equals(that.recorder())) && (this.currentServerSpan.equals(that.currentServerSpan())) && (this.currentSpan.equals(that.currentSpan())) && (this.allowNestedLocalSpans == that.allowNestedLocalSpans()) && (this.spanFactory.equals(that.spanFactory())); } return false; }
/** * Request a new local span, which starts now. * * @param component {@link zipkinCoreConstants#LOCAL_COMPONENT component} responsible for the operation * @param operation name of the operation that's begun * @return metadata about the new span or null if one wasn't started due to sampling policy. * @see zipkinCoreConstants#LOCAL_COMPONENT */ public SpanId startNewSpan(String component, String operation) { SpanId spanId = startNewSpan(component, operation, currentTimeMicroseconds()); if (spanId == null) return null; spanAndEndpoint().span().startTick = System.nanoTime(); // embezzle start tick into an internal field. return spanId; }
@Override public List<List<Span>> getTraces(QueryRequest request) { if (tracer.startNewSpan(component, "get-traces") != null) { tracer.submitBinaryAnnotation("request", request.toString()); } try { return delegate.getTraces(request); } finally { tracer.finishSpan(); } }
/** * Completes the span, assigning the most precise duration possible. */ public void finishSpan() { long endTick = System.nanoTime(); Span span = spanAndEndpoint().span(); if (span == null) return; Long startTick = span.startTick; final long duration; if (startTick != null) { duration = (endTick - startTick) / 1000; } else { duration = currentTimeMicroseconds() - span.getTimestamp(); } finishSpan(duration); }
Span newSpan() { // When a trace context is extracted from an incoming request, it may have only the // sampled header (no ids). If the header says unsampled, we must honor that. Since // we currently don't synthesize a fake span when a trace is unsampled, we have to // check sampled state explicitly. Boolean sample = currentServerSpan().sampled(); if (Boolean.FALSE.equals(sample)) { currentSpan().setCurrentSpan(null); return null; } Span span = spanFactory().nextSpan(maybeParent()); SpanId context = Brave.context(span); if (Boolean.FALSE.equals(context.sampled())) { currentSpan().setCurrentSpan(null); return null; } return span; }
/** * Request the span that should be considered the new span's parent. * * If {@link #allowNestedLocalSpans()} is enabled, the new span's parent * will be the current local span (if one exists). * * If nested local spans is not enabled or there is no current local span, * the new span's parent will be the current server span (if one exists). * * @return span that should be the new span's parent, or null if one does not exist. */ @Nullable SpanId maybeParent() { Span parentSpan = null; if (allowNestedLocalSpans()) { parentSpan = currentSpan().get(); } if (parentSpan == null) { Span currentServerSpan = currentServerSpan().get(); if (currentServerSpan != null) { parentSpan = currentServerSpan; } } if (parentSpan == null) return null; return Brave.context(parentSpan); }
/** * Completes the span, assigning the most precise duration possible. */ public void finishSpan() { Span span = currentSpan().get(); if (span == null) return; recorder().finish(span, recorder().currentTimeMicroseconds(span)); currentSpan().setCurrentSpan(null); }
Boolean sample = spanAndEndpoint().state().sample(); if (Boolean.FALSE.equals(sample)) { spanAndEndpoint().state().setCurrentLocalSpan(null); return null; SpanId newSpanId = getNewSpanId(); if (sample == null) { if (!traceSampler().isSampled(newSpanId.traceId)) { spanAndEndpoint().state().setCurrentLocalSpan(null); return null; newSpan.setTimestamp(timestamp); newSpan.addToBinary_annotations( BinaryAnnotation.create(LOCAL_COMPONENT, component, spanAndEndpoint().endpoint())); spanAndEndpoint().state().setCurrentLocalSpan(newSpan); return newSpanId;
private Brave(Builder builder) { serverTracer = ServerTracer.builder() .randomGenerator(builder.random) .spanCollector(builder.spanCollector) .state(builder.state) .traceSampler(builder.sampler).build(); clientTracer = ClientTracer.builder() .randomGenerator(builder.random) .spanCollector(builder.spanCollector) .state(builder.state) .traceSampler(builder.sampler).build(); localTracer = LocalTracer.builder() .randomGenerator(builder.random) .spanCollector(builder.spanCollector) .spanAndEndpoint(SpanAndEndpoint.LocalSpanAndEndpoint.create(builder.state)) .traceSampler(builder.sampler).build(); serverRequestInterceptor = new ServerRequestInterceptor(serverTracer); serverResponseInterceptor = new ServerResponseInterceptor(serverTracer); clientRequestInterceptor = new ClientRequestInterceptor(clientTracer); clientResponseInterceptor = new ClientResponseInterceptor(clientTracer); serverSpanAnnotationSubmitter = AnnotationSubmitter.create(SpanAndEndpoint.ServerSpanAndEndpoint.create(builder.state)); serverSpanThreadBinder = new ServerSpanThreadBinder(builder.state); clientSpanThreadBinder = new ClientSpanThreadBinder(builder.state); } }
SpanId startSpan(String component, String operation, long timestamp, Span span) { recorder().start(span, timestamp); recorder().name(span, operation); recorder().tag(span, "lc", component); currentSpan().setCurrentSpan(span); return Brave.context(span); }
@Override public List<String> getServiceNames() { tracer.startNewSpan(component, "get-service-names"); try { return delegate.getServiceNames(); } finally { tracer.finishSpan(); } }
/** * Completes the span, which took {@code duration} microseconds. */ public void finishSpan(long duration) { Span span = currentSpan().get(); if (span == null) return; final Long timestamp; synchronized (span) { timestamp = span.getTimestamp(); } if (timestamp == null) { recorder().flush(span); } else { recorder().finish(span, timestamp + duration); } currentSpan().setCurrentSpan(null); }
@Override public List<String> getSpanNames(String serviceName) { tracer.startNewSpan(component, "get-span-names"); try { return delegate.getSpanNames(serviceName); } finally { tracer.finishSpan(); } }
@Override public List<DependencyLink> getDependencies(long endTs, @Nullable Long lookback) { tracer.startNewSpan(component, "get-dependencies"); try { return delegate.getDependencies(endTs, lookback); } finally { tracer.finishSpan(); } } }
public void record(ApplicationEvent event) { annotations.put(event.getClass().getSimpleName().replace("Event", ""), timestamp + microsSinceInit()); // record duration and flush the trace if we're done if (event instanceof ApplicationReadyEvent) { long duration = microsSinceInit(); // get duration now, as below logic might skew things. ApplicationReadyEvent ready = (ApplicationReadyEvent) event; LocalTracer tracer = ready.getApplicationContext().getBeanFactory() .getBean(Brave.class).localTracer(); tracer.startNewSpan("spring-boot", "bootstrap", timestamp); annotations.forEach(tracer::submitAnnotation); tracer.finishSpan(duration); } }
@Test public void usesExistingTraceId_local() throws Exception { server.enqueue(new MockResponse()); SpanId parent = brave.localTracer().startNewSpan(getClass().getSimpleName(), "test"); try { get(client, "/foo"); } finally { brave.localTracer().finishSpan(); } RecordedRequest request = server.takeRequest(); assertThat(request.getHeader("x-b3-traceId")) .isEqualTo(parent.traceIdString()); assertThat(request.getHeader("x-b3-parentspanid")) .endsWith(IdConversion.convertToString(parent.spanId)); }
/** * This tests that the parent is determined at the time the request was made, not when the request * was executed. */ @Test public void usesParentFromInvocationTime_local() throws Exception { server.enqueue(new MockResponse().setBodyDelay(1, TimeUnit.SECONDS)); server.enqueue(new MockResponse()); SpanId parent = brave.localTracer().startNewSpan(getClass().getSimpleName(), "test"); try { getAsync(client, "/foo"); getAsync(client, "/foo"); } finally { brave.localTracer().finishSpan(); } // changing the local span after the fact! brave.localTracer().startNewSpan(getClass().getSimpleName(), "test"); try { for (int i = 0; i < 2; i++) { RecordedRequest request = server.takeRequest(); assertThat(request.getHeader("x-b3-traceId")) .isEqualTo(parent.traceIdString()); assertThat(request.getHeader("x-b3-parentspanid")) .endsWith(IdConversion.convertToString(parent.spanId)); } } finally { brave.localTracer().finishSpan(); } }