All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.kristofa.brave.ServerTracer Maven / Gradle / Ivy

The newest version!
package com.github.kristofa.brave;

import com.google.auto.value.AutoValue;

import com.github.kristofa.brave.SpanAndEndpoint.ServerSpanAndEndpoint;
import com.github.kristofa.brave.internal.Nullable;
import com.twitter.zipkin.gen.Endpoint;
import com.twitter.zipkin.gen.zipkinCoreConstants;

import java.util.Random;

import static com.github.kristofa.brave.internal.Util.checkNotBlank;

/**
 * Used for setting up trace information for a request. When a request is received we typically do this:
 * 
    *
  1. Detect if we are part of existing trace/span. For example with services doing http requests this can be done by * detecting and getting values of http header that reresent trace/span ids.
  2. *
  3. Once detected we submit state using one of 3 following methods depending on the state we are in: * {@link ServerTracer#setStateCurrentTrace(long, long, Long, String), {@link ServerTracer#setStateNoTracing()} or * {@link ServerTracer#setStateUnknown(String)}.
  4. *
  5. Next we execute {@link ServerTracer#setServerReceived()} to mark the point in time at which we received the request.
  6. *
  7. Service request executes its logic... *
  8. Just before sending response we execute {@link ServerTracer#setServerSend()}. *
* * @author kristof */ @AutoValue public abstract class ServerTracer extends AnnotationSubmitter { public static Builder builder() { return new AutoValue_ServerTracer.Builder(); } @Override abstract ServerSpanAndEndpoint spanAndEndpoint(); abstract Random randomGenerator(); abstract SpanCollector spanCollector(); abstract Sampler traceSampler(); @AutoValue.Builder public abstract static class Builder { public Builder state(ServerSpanState state) { return spanAndEndpoint(ServerSpanAndEndpoint.create(state)); } abstract Builder spanAndEndpoint(ServerSpanAndEndpoint spanAndEndpoint); /** * Used to generate new trace/span ids. */ public abstract Builder randomGenerator(Random randomGenerator); public abstract Builder spanCollector(SpanCollector spanCollector); public abstract Builder traceSampler(Sampler sampler); public abstract ServerTracer build(); } /** * Clears current span. */ public void clearCurrentSpan() { spanAndEndpoint().state().setCurrentServerSpan(null); } /** * Sets the current Trace/Span state. Using this method indicates we are part of an existing trace/span. * * @param traceId Trace id. * @param spanId Span id. * @param parentSpanId Parent span id. Can be null. * @param name Name should not be empty or null. * @see ServerTracer#setStateNoTracing() * @see ServerTracer#setStateUnknown(String) */ public void setStateCurrentTrace(long traceId, long spanId, @Nullable Long parentSpanId, @Nullable String name) { checkNotBlank(name, "Null or blank span name"); spanAndEndpoint().state().setCurrentServerSpan( ServerSpan.create(traceId, spanId, parentSpanId, name)); } /** * Sets the current Trace/Span state. Using this method indicates that a parent request has decided that we should not * trace the current request. * * @see ServerTracer#setStateCurrentTrace(long, long, Long, String) * @see ServerTracer#setStateUnknown(String) */ public void setStateNoTracing() { spanAndEndpoint().state().setCurrentServerSpan(ServerSpan.NOT_SAMPLED); } /** * Sets the current Trace/Span state. Using this method indicates that we got no information about being part of an * existing trace or about the fact that we should not trace the current request. In this case the ServerTracer will * decide what to do. * * @param spanName The name of our current request/span. */ public void setStateUnknown(String spanName) { checkNotBlank(spanName, "Null or blank span name"); long newTraceId = randomGenerator().nextLong(); if (!traceSampler().isSampled(newTraceId)) { spanAndEndpoint().state().setCurrentServerSpan(ServerSpan.NOT_SAMPLED); return; } spanAndEndpoint().state().setCurrentServerSpan( ServerSpan.create(newTraceId, newTraceId, null, spanName)); } /** * Sets server received event for current request. This should be done after setting state using one of 3 methods * {@link ServerTracer#setStateCurrentTrace(long, long, Long, String)} , {@link ServerTracer#setStateNoTracing()} or * {@link ServerTracer#setStateUnknown(String)}. */ public void setServerReceived() { submitStartAnnotation(zipkinCoreConstants.SERVER_RECV); } /** * Like {@link #setServerReceived()}, except you can log the network context of the caller, for * example an IP address from the {@code X-Forwarded-For} header. * * @param ipv4 ipv4 of the client as an int. Ex for 1.2.3.4, it would be (1 << 24) | (2 << 16) | (3 << 8) | 4 * @param port port for client-side of the socket, or 0 if unknown * @param clientService lowercase {@link Endpoint#service_name name} of the callee service or * null if unknown */ public void setServerReceived(int ipv4, int port, @Nullable String clientService) { submitAddress(zipkinCoreConstants.CLIENT_ADDR, ipv4, port, clientService); submitStartAnnotation(zipkinCoreConstants.SERVER_RECV); } /** * Sets the server sent event for current thread. */ public void setServerSend() { if (submitEndAnnotation(zipkinCoreConstants.SERVER_SEND, spanCollector())) { spanAndEndpoint().state().setCurrentServerSpan(null); } } ServerTracer() { } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy