committed by
Marcin Grzejszczak
parent
be1b986bec
commit
3000a4f37d
@@ -19,7 +19,7 @@ package org.springframework.cloud.sleuth;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
/**
|
||||
* Default implementation of SpanNamer that tries to get the Span name as follows:
|
||||
* Default implementation of SpanNamer that tries to get the span name as follows:
|
||||
*
|
||||
* <li>
|
||||
* <ul>from the @SpanName annotation if one is present</ul>
|
||||
@@ -28,9 +28,10 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
* <ul>the default provided value</ul>
|
||||
* </li>
|
||||
*
|
||||
* @see org.springframework.cloud.sleuth.SpanName
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see org.springframework.cloud.sleuth.SpanName
|
||||
*/
|
||||
public class DefaultSpanNamer implements SpanNamer {
|
||||
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
package org.springframework.cloud.sleuth;
|
||||
|
||||
/**
|
||||
* Represents an event in time associated with a span. Every span has zero or more Logs,
|
||||
* each of which being a timestamped event name.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class Log {
|
||||
/**
|
||||
@@ -26,22 +30,16 @@ public class Log {
|
||||
private final long timestamp;
|
||||
|
||||
/**
|
||||
* Event (if not null) should be the stable name of some notable moment in the lifetime of a Span.
|
||||
* For instance, a Span representing a browser page load might add an Event for each of the
|
||||
* Event (if not null) should be the stable name of some notable moment in the lifetime of a span.
|
||||
* For instance, a span representing a browser page load might add an Event for each of the
|
||||
* Performance.timing moments here: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceTiming
|
||||
*
|
||||
* <p>While it is not a formal requirement, Event strings will be most useful if they are *not*
|
||||
* unique; rather, tracing systems should be able to use them to understand how two similar Spans
|
||||
* unique; rather, tracing systems should be able to use them to understand how two similar spans
|
||||
* relate from an internal timing perspective.
|
||||
*/
|
||||
private final String event;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Log() {
|
||||
this.timestamp = 0;
|
||||
this.event = null;
|
||||
}
|
||||
|
||||
public Log(long timestamp, String event) {
|
||||
this.timestamp = timestamp;
|
||||
this.event = event;
|
||||
|
||||
@@ -18,10 +18,12 @@ package org.springframework.cloud.sleuth;
|
||||
|
||||
/**
|
||||
* Extremely simple callback to determine the frequency that an action should be traced.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface Sampler {
|
||||
/**
|
||||
* @param span the current span (or null if there is none)
|
||||
* @return true if the span is not null and should be exported to the tracing system
|
||||
*/
|
||||
boolean isSampled(Span span);
|
||||
}
|
||||
|
||||
@@ -29,13 +29,25 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Class for gathering and reporting statistics about a block of execution.
|
||||
* <p/>
|
||||
* <p>
|
||||
* Spans should form a directed acyclic graph structure. It should be possible to keep
|
||||
* following the parents of a span until you arrive at a span with no parents.
|
||||
* <p/>
|
||||
* <p>
|
||||
* Spans can be either annotated with tags or logs.
|
||||
* <p>
|
||||
* An <b>Annotation</b> is used to record existence of an event in time. Below you can find some
|
||||
* of the core annotations used to define the start and stop of a request:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li><b>cs</b> - {@link org.springframework.cloud.sleuth.event.ClientSentEvent Client Sent}</li>
|
||||
* <li><b>sr</b> - {@link org.springframework.cloud.sleuth.event.ServerReceivedEvent Server Received}</li>
|
||||
* <li><b>ss</b> - {@link org.springframework.cloud.sleuth.event.ServerSentEvent Server Sent}</li>
|
||||
* <li><b>cr</b> - {@link org.springframework.cloud.sleuth.event.ClientReceivedEvent Client Received}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
/*
|
||||
* OpenTracing spans can affect the trace tree by creating children. In this way, they are
|
||||
@@ -186,7 +198,7 @@ public class Span {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the saved span. The one that was "current" before this Span.
|
||||
* Returns the saved span. The one that was "current" before this span.
|
||||
* <p>
|
||||
* Might be null
|
||||
*/
|
||||
@@ -210,7 +222,7 @@ public class Span {
|
||||
* A pseudo-unique (random) number assigned to this span instance.
|
||||
* <p>
|
||||
* <p>
|
||||
* The spanId is immutable and cannot be changed. It is safe to access this from
|
||||
* The span id is immutable and cannot be changed. It is safe to access this from
|
||||
* multiple threads.
|
||||
*/
|
||||
public long getSpanId() {
|
||||
@@ -225,10 +237,9 @@ public class Span {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a unique id for the process from which this Span originated.
|
||||
* Return a unique id for the process from which this span originated.
|
||||
* <p>
|
||||
* <p>
|
||||
* // TODO: Check when this is going to be null (cause it may be null)
|
||||
* Might be null
|
||||
*/
|
||||
public String getProcessId() {
|
||||
return this.processId;
|
||||
|
||||
@@ -22,7 +22,7 @@ package org.springframework.cloud.sleuth;
|
||||
* to specialized and cross-cutting instrumentation code).
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface SpanAccessor {
|
||||
|
||||
|
||||
@@ -23,16 +23,40 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* Annotation to provide the name for the Span. You should annotate all your
|
||||
* custom {@link java.lang.Runnable} or {@link java.util.concurrent.Callable} classes
|
||||
* Annotation to provide the name for the span. You should annotate all your
|
||||
* custom {@link java.lang.Runnable Runnable} or {@link java.util.concurrent.Callable Callable} classes
|
||||
* for the instrumentation logic to pick up how to name the span.
|
||||
* <p>
|
||||
*
|
||||
* If you're using anonymous instances for those classes then you should override the
|
||||
* {@code toString()} method. That way that value will be picked as a span name at
|
||||
* runtime.
|
||||
* Having for example the following code
|
||||
* <pre>{@code
|
||||
* @SpanName("custom-operation")
|
||||
* class CustomRunnable implements Runnable {
|
||||
* @Override
|
||||
* public void run() {
|
||||
* // latency of this method will be recorded in a span named "custom-operation"
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* Will result in creating a span with name {@code custom-operation}.
|
||||
* <p>
|
||||
*
|
||||
* When there's no @SpanName annotation, {@code toString} is used. Here's an
|
||||
* example of the above, but via an anonymous instance.
|
||||
* <pre>{@code
|
||||
* return new Runnable() {
|
||||
* -- snip --
|
||||
*
|
||||
* @Override
|
||||
* public String toString() {
|
||||
* return "custom-operation";
|
||||
* }
|
||||
* };
|
||||
* }</pre>
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -23,6 +23,7 @@ package org.springframework.cloud.sleuth;
|
||||
* the name of the span.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface SpanNamer {
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.concurrent.Callable;
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceCallable<V> implements Callable<V> {
|
||||
|
||||
|
||||
@@ -45,6 +45,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* Meanwhile, you have another system storing private data! The takeaway isn't never store
|
||||
* cookies, as there are valid cases for this. The takeaway is to be conscious about
|
||||
* what's you are storing.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.sleuth.keys")
|
||||
public class TraceKeys {
|
||||
|
||||
@@ -23,9 +23,16 @@ package org.springframework.cloud.sleuth;
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceRunnable implements Runnable {
|
||||
|
||||
/**
|
||||
* Since we don't know the exact operation name we provide a default
|
||||
* name for the Span
|
||||
*/
|
||||
private static final String DEFAULT_SPAN_NAME = "async";
|
||||
|
||||
private final Tracer tracer;
|
||||
private final SpanNamer spanNamer;
|
||||
private final Runnable delegate;
|
||||
@@ -63,7 +70,7 @@ public class TraceRunnable implements Runnable {
|
||||
if (this.name != null) {
|
||||
return this.name;
|
||||
}
|
||||
return this.spanNamer.name(this.delegate, "async");
|
||||
return this.spanNamer.name(this.delegate, DEFAULT_SPAN_NAME);
|
||||
}
|
||||
|
||||
protected void close(Span span) {
|
||||
|
||||
@@ -21,28 +21,36 @@ import java.util.concurrent.Callable;
|
||||
/**
|
||||
* The TraceManager class is the primary way for instrumentation code (note user code) to
|
||||
* interact with the library. It provides methods to create and manipulate spans.
|
||||
* <p>
|
||||
*
|
||||
* A 'Span' represents a length of time. It has many other attributes such as a name, ID,
|
||||
* A 'span' represents a length of time. It has many other attributes such as a name, ID,
|
||||
* and even potentially a set of key/value strings attached to it.
|
||||
* <p>
|
||||
*
|
||||
* Each thread in your application has a single currently active currentSpan associated
|
||||
* with it. When this is non-null, it represents the current operation that the thread is
|
||||
* doing. Spans are NOT thread-safe, and must never be used by multiple threads at once.
|
||||
* With care, it is possible to safely pass a Span object between threads, but in most
|
||||
* doing. spans are NOT thread-safe, and must never be used by multiple threads at once.
|
||||
* With care, it is possible to safely pass a span object between threads, but in most
|
||||
* cases this is not necessary.
|
||||
* <p>
|
||||
*
|
||||
* The 'startTrace' method in this class starts a new span.
|
||||
*
|
||||
* <li>Create a TraceSpan object to manage the new Span.</li>
|
||||
* Most crucial methods in terms of span lifecycle are:
|
||||
* <ul>
|
||||
* <li>The {@linkplain Tracer#startTrace(String) startTrace} method in this class
|
||||
* starts a new span.</li>
|
||||
* <li>The {@linkplain Tracer#joinTrace(String, Span) joinTrace} method creates a new span
|
||||
* which has this thread's currentSpan as one of its parents</li>
|
||||
* <li>The {@linkplain Tracer#continueSpan(Span) continueSpan} method creates a
|
||||
* new instance of span that logically is a continuation of the provided span.</li>
|
||||
* </ul>
|
||||
*
|
||||
* The 'joinTrace' method creates a new Span which has this thread's currentSpan as one of its parents
|
||||
*
|
||||
* Closing a TraceScope does a few things:
|
||||
* <ul>
|
||||
* <li>It closes the span which the scope was managing.</li>
|
||||
* <li>Set currentSpan to the previous currentSpan (which may be null).</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface Tracer extends SpanAccessor {
|
||||
|
||||
@@ -72,25 +80,44 @@ public interface Tracer extends SpanAccessor {
|
||||
/**
|
||||
* Start a new span if the sampler allows it or if we are already tracing in this
|
||||
* thread. A sampler can be used to limit the number of traces created.
|
||||
* @param name the name of the span
|
||||
*
|
||||
* @param name the name of the span
|
||||
* @param sampler a sampler to decide whether to create the span or not
|
||||
*/
|
||||
Span startTrace(String name, Sampler sampler);
|
||||
|
||||
/**
|
||||
* Pick up an existing span from another thread.
|
||||
* Contributes to a span started in another thread. The returned span shares
|
||||
* mutable state with the input.
|
||||
*/
|
||||
Span continueSpan(Span span);
|
||||
|
||||
/**
|
||||
* Adds a tag to the current span if tracing is currently on.
|
||||
* <p>
|
||||
* Every span may also have zero or more key/value Tags, which do not have
|
||||
* timestamps and simply annotate the spans.
|
||||
*
|
||||
* Check {@link TraceKeys} for examples of most common tag keys
|
||||
*/
|
||||
void addTag(String key, String value);
|
||||
|
||||
/**
|
||||
* Remove this span from the current thread, but don't stop it yet or send it for
|
||||
* collection. This is useful if the span object is then passed to another thread for
|
||||
* use with Span.continueTrace().
|
||||
* use with {@link Tracer#continueSpan(Span)}.
|
||||
* <p>
|
||||
* Example of usage:
|
||||
* <pre>{@code
|
||||
* // Span "A" was present in thread "X". Let's assume that we're in thread "Y" to which span "A" got passed
|
||||
* Span continuedSpan = tracer.continueSpan(spanA);
|
||||
* // Now span "A" got continued in thread "Y".
|
||||
* ... // Some work is done... state of span "A" could get mutated
|
||||
* Span previouslyStoredSpan = tracer.detach(continuedSpan);
|
||||
* // Span "A" got removed from the thread Y but it wasn't yet sent for collection.
|
||||
* // Additional work can be done on span "A" in thread "X" and finally it can get closed and sent for collection
|
||||
* tracer.close(spanA);
|
||||
* }</pre>
|
||||
*
|
||||
* @return the saved trace if there was one before the trace started (null otherwise)
|
||||
*/
|
||||
@@ -104,7 +131,15 @@ public interface Tracer extends SpanAccessor {
|
||||
*/
|
||||
Span close(Span span);
|
||||
|
||||
/**
|
||||
* Returns a wrapped {@link Callable} which will be recorded as a span
|
||||
* in the current trace.
|
||||
*/
|
||||
<V> Callable<V> wrap(Callable<V> callable);
|
||||
|
||||
/**
|
||||
* Returns a wrapped {@link Runnable} which will be recorded as a span
|
||||
* in the current trace.
|
||||
*/
|
||||
Runnable wrap(Runnable runnable);
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.cloud.sleuth.DefaultSpanNamer;
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.TraceKeys;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.sampler.NeverSampler;
|
||||
import org.springframework.cloud.sleuth.trace.DefaultTracer;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
@@ -33,7 +33,12 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* to enable tracing via Spring Cloud Sleuth.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value="spring.sleuth.enabled", matchIfMissing=true)
|
||||
|
||||
@@ -27,10 +27,18 @@ import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
|
||||
/**
|
||||
* Adds a default logging pattern level that prints trace infotmation
|
||||
* Adds default properties for the application:
|
||||
* <ul>
|
||||
* <li>logging pattern level that prints trace information (e.g. trace ids)</li>
|
||||
* <li>enables usage of subclass-based (CGLIB) proxies are to be created as opposed
|
||||
* to standard Java interface-based proxies</li>
|
||||
* It's required for the tracing aspects like
|
||||
* {@link org.springframework.cloud.sleuth.instrument.async.TraceAsyncAspect TraceAsyncAspect} or
|
||||
* {@link org.springframework.cloud.sleuth.instrument.scheduling.TraceSchedulingAspect TraceSchedulingAspect}.
|
||||
* </ul>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
||||
|
||||
|
||||
@@ -23,7 +23,11 @@ import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
/**
|
||||
* Accumulator of {@link org.springframework.cloud.sleuth.Tracer#close(Span)
|
||||
* closed spans}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ArrayListSpanAccumulator implements ApplicationListener<SpanReleasedEvent> {
|
||||
private final List<Span> spans = new ArrayList<>();
|
||||
|
||||
@@ -19,8 +19,14 @@ package org.springframework.cloud.sleuth.event;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* <b>cr</b> - Client Receive. Signifies the end of the span. The client has successfully received the
|
||||
* response from the server side. If one subtracts the cs timestamp from this timestamp one
|
||||
* will receive the whole time needed by the client to receive the response from the server.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see ClientSentEvent
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ClientReceivedEvent extends SpanContainingEvent {
|
||||
|
||||
@@ -19,8 +19,12 @@ package org.springframework.cloud.sleuth.event;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* <b>cs</b> - Client Sent. The client has made a request (a client can be e.g.
|
||||
* {@link org.springframework.web.client.RestTemplate}. This annotation depicts
|
||||
* the start of the span.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ClientSentEvent extends SpanContainingEvent {
|
||||
|
||||
@@ -19,7 +19,13 @@ package org.springframework.cloud.sleuth.event;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* <b>sr</b> - Server Receive. The server side got the request and will start processing it.
|
||||
* If one subtracts the cs timestamp from this timestamp one will receive the network latency.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see ClientSentEvent
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ServerReceivedEvent extends SpanParentContainingEvent {
|
||||
|
||||
@@ -19,7 +19,14 @@ package org.springframework.cloud.sleuth.event;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* <b>ss</b> - Server Send. Annotated upon completion of request processing (when the response
|
||||
* got sent back to the client). If one subtracts the sr timestamp from this timestamp one
|
||||
* will receive the time needed by the server side to process the request.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see ServerReceivedEvent
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ServerSentEvent extends SpanParentContainingEvent {
|
||||
|
||||
@@ -19,7 +19,10 @@ package org.springframework.cloud.sleuth.event;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* Event emitted when a parent or a child span was created.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SpanAcquiredEvent extends SpanParentContainingEvent {
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.context.ApplicationEvent;
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class SpanContainingEvent extends ApplicationEvent {
|
||||
abstract class SpanContainingEvent extends ApplicationEvent {
|
||||
private final Span span;
|
||||
|
||||
public SpanContainingEvent(Object source, Span span) {
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.springframework.cloud.sleuth.event;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* Emitted when a span was continued.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.context.ApplicationEvent;
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class SpanParentContainingEvent extends ApplicationEvent {
|
||||
abstract class SpanParentContainingEvent extends ApplicationEvent {
|
||||
|
||||
private final Span span;
|
||||
private final Span parent;
|
||||
|
||||
@@ -19,6 +19,9 @@ package org.springframework.cloud.sleuth.event;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* Event emitted upon closing of a span. Results in preparing span for collection
|
||||
* to external systems (logging, Zipkin etc.)
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.TraceKeys;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface SpanExtractor<T, U> {
|
||||
|
||||
Span extract(T input, TraceKeys keys);
|
||||
|
||||
void inject(Span span, U output, TraceKeys keys);
|
||||
|
||||
}
|
||||
@@ -28,6 +28,13 @@ import org.springframework.cloud.sleuth.instrument.scheduling.TraceSchedulingAut
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* that wraps an existing custom {@link AsyncConfigurer} in a {@link LazyTraceAsyncCustomizer}
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean(AsyncConfigurer.class)
|
||||
@AutoConfigureBefore(AsyncDefaultAutoConfiguration.class)
|
||||
|
||||
@@ -33,20 +33,35 @@ import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enabling async related processing.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see LazyTraceExecutor
|
||||
* @see TraceAsyncAspect
|
||||
*/
|
||||
@EnableAsync
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(AsyncConfigurer.class)
|
||||
@ConditionalOnProperty(value = "spring.sleuth.async.enabled", matchIfMissing = true)
|
||||
@ConditionalOnBean(Tracer.class)
|
||||
@AutoConfigureAfter(AsyncCustomAutoConfiguration.class)
|
||||
public class AsyncDefaultAutoConfiguration extends AsyncConfigurerSupport {
|
||||
public class AsyncDefaultAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(AsyncConfigurer.class)
|
||||
@ConditionalOnProperty(value = "spring.sleuth.async.configurer.enabled", matchIfMissing = true)
|
||||
static class DefaultAsyncConfigurerSupport extends AsyncConfigurerSupport {
|
||||
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
return new LazyTraceExecutor(this.beanFactory, new SimpleAsyncTaskExecutor());
|
||||
@Autowired private BeanFactory beanFactory;
|
||||
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
return new LazyTraceExecutor(this.beanFactory, new SimpleAsyncTaskExecutor());
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class LazyTraceAsyncCustomizer extends AsyncConfigurerSupport {
|
||||
|
||||
|
||||
@@ -25,12 +25,16 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.cloud.sleuth.DefaultSpanNamer;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.TraceKeys;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* {@link Executor} that wraps {@link Runnable} in a
|
||||
* {@link org.springframework.cloud.sleuth.TraceRunnable TraceRunnable} that sets a
|
||||
* local component tag on the span.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class LazyTraceExecutor implements Executor {
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@ import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.TraceKeys;
|
||||
|
||||
/**
|
||||
*
|
||||
* Callable that starts a span that is a local component span.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class LocalComponentTraceCallable<V> extends TraceCallable<V> {
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.TraceKeys;
|
||||
|
||||
/**
|
||||
*
|
||||
* Runnable that starts a span that is a local component span.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class LocalComponentTraceRunnable extends TraceRunnable {
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.cloud.sleuth.TraceKeys;
|
||||
* {@link org.springframework.scheduling.annotation.Async} annotation.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see Tracer
|
||||
*/
|
||||
|
||||
@@ -24,7 +24,8 @@ import org.springframework.cloud.sleuth.TraceCallable;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
/**
|
||||
* Trace Callable that continues a span instead of creating a new one
|
||||
* Trace Callable that continues a span instead of creating a new one. Upon completion
|
||||
* the span is not closed - it gets {@link Tracer#detach(Span) detached}.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
|
||||
@@ -30,8 +30,9 @@ import org.springframework.cloud.sleuth.TraceKeys;
|
||||
|
||||
/**
|
||||
* A decorator class for {@link ExecutorService} to support tracing in Executors
|
||||
* @author Gaurav Rai Mazra
|
||||
*
|
||||
* @author Gaurav Rai Mazra
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceableExecutorService implements ExecutorService {
|
||||
final ExecutorService delegate;
|
||||
|
||||
@@ -27,8 +27,9 @@ import org.springframework.cloud.sleuth.TraceKeys;
|
||||
|
||||
/**
|
||||
* A decorator class for {@link ScheduledExecutorService} to support tracing in Executors
|
||||
* @author Gaurav Rai Mazra
|
||||
*
|
||||
* @author Gaurav Rai Mazra
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceableScheduledExecutorService extends TraceableExecutorService implements ScheduledExecutorService {
|
||||
|
||||
|
||||
@@ -9,6 +9,15 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.netflix.hystrix.HystrixCommand;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* that registers a custom Sleuth {@link com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy}.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see SleuthHystrixConcurrencyStrategy
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(HystrixCommand.class)
|
||||
@ConditionalOnProperty(value = "spring.sleuth.hystrix.strategy.enabled", matchIfMissing = true)
|
||||
|
||||
@@ -13,6 +13,14 @@ import org.springframework.cloud.sleuth.TraceKeys;
|
||||
import com.netflix.hystrix.strategy.HystrixPlugins;
|
||||
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
||||
|
||||
/**
|
||||
* A {@link HystrixConcurrencyStrategy} that wraps a {@link Callable} in a
|
||||
* {@link Callable} that either starts a new span or continues one
|
||||
* if the tracing was already running before the command was executed.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
|
||||
|
||||
private static final String HYSTRIX_COMPONENT = "hystrix";
|
||||
|
||||
@@ -49,6 +49,15 @@ public class SpanMessageHeaders {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds default headers for a message. Check {@link Span} constants for
|
||||
* more information what the default headers are.
|
||||
*
|
||||
* @param traceKeys - the global configuration for trace keys
|
||||
* @param message - message to which headers will be added
|
||||
* @param span - span from which headers will be taken
|
||||
* @return the input message with updated headers
|
||||
*/
|
||||
public static Message<?> addSpanHeaders(TraceKeys traceKeys, Message<?> message,
|
||||
Span span) {
|
||||
|
||||
|
||||
@@ -27,8 +27,10 @@ import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* A channel interceptor that automatically starts / continues / closes and detaches spans.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceChannelInterceptor extends AbstractTraceChannelInterceptor {
|
||||
|
||||
|
||||
@@ -31,7 +31,13 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.config.GlobalChannelInterceptor;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* that registers a Sleuth version of the {@link org.springframework.messaging.support.ChannelInterceptor}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see TraceChannelInterceptor
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(GlobalChannelInterceptor.class)
|
||||
|
||||
@@ -14,6 +14,15 @@ import org.springframework.web.socket.config.annotation.AbstractWebSocketMessage
|
||||
import org.springframework.web.socket.config.annotation.DelegatingWebSocketMessageBrokerConfiguration;
|
||||
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* that enables tracing for WebSockets.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see AbstractWebSocketMessageBrokerConfigurer
|
||||
*/
|
||||
@Component
|
||||
@ConditionalOnClass(DelegatingWebSocketMessageBrokerConfiguration.class)
|
||||
@ConditionalOnBean(AbstractWebSocketMessageBrokerConfigurer.class)
|
||||
|
||||
@@ -25,12 +25,15 @@ import org.springframework.cloud.sleuth.Tracer;
|
||||
/**
|
||||
* Aspect that creates a new Span for running threads executing methods annotated with
|
||||
* {@link org.springframework.scheduling.annotation.Scheduled} annotation.
|
||||
* For every execution of scheduled method a new trace will be started.
|
||||
* For every execution of scheduled method a new trace will be started. The name of the
|
||||
* span will be the simple name of the class annotated with
|
||||
* {@link org.springframework.scheduling.annotation.Scheduled}
|
||||
*
|
||||
* @author Tomasz Nurkewicz, 4financeIT
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Spencer Gibb
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see Tracer
|
||||
*/
|
||||
@@ -47,8 +50,9 @@ public class TraceSchedulingAspect {
|
||||
|
||||
@Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))")
|
||||
public Object traceBackgroundThread(final ProceedingJoinPoint pjp) throws Throwable {
|
||||
String spanName = SCHEDULED_COMPONENT + ":" + pjp.getTarget().getClass().getSimpleName();
|
||||
String spanName = pjp.getTarget().getClass().getSimpleName();
|
||||
Span span = this.tracer.startTrace(spanName);
|
||||
this.tracer.addTag(Span.SPAN_LOCAL_COMPONENT_TAG_NAME, SCHEDULED_COMPONENT);
|
||||
try {
|
||||
return pjp.proceed();
|
||||
}
|
||||
|
||||
@@ -34,10 +34,11 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
/**
|
||||
* Registers beans related to task scheduling.
|
||||
*
|
||||
* @see TraceSchedulingAspect
|
||||
*
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @see TraceSchedulingAspect
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAspectJAutoProxy
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
*/
|
||||
package org.springframework.cloud.sleuth.instrument.web;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -26,12 +22,17 @@ import java.util.Enumeration;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Span.SpanBuilder;
|
||||
import org.springframework.cloud.sleuth.TraceKeys;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.event.ServerReceivedEvent;
|
||||
import org.springframework.cloud.sleuth.event.ServerSentEvent;
|
||||
import org.springframework.cloud.sleuth.TraceKeys;
|
||||
import org.springframework.cloud.sleuth.sampler.NeverSampler;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
@@ -54,15 +55,17 @@ import static org.springframework.util.StringUtils.hasText;
|
||||
* {@link TraceKeys}. If you need to add additional tags, such as headers subtype this and
|
||||
* override {@link #addRequestTags} or {@link #addResponseTags}.
|
||||
*
|
||||
* @author Jakub Nabrdalik, 4financeIT
|
||||
* @author Tomasz Nurkiewicz, 4financeIT
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @see Tracer
|
||||
* @see TraceKeys
|
||||
* @see TraceWebAutoConfiguration#traceFilter
|
||||
*
|
||||
* @author Jakub Nabrdalik, 4financeIT
|
||||
* @author Tomasz Nurkiewicz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE + 5)
|
||||
public class TraceFilter extends OncePerRequestFilter
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.web;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class TraceHandlerInterceptor implements HandlerInterceptor {
|
||||
|
||||
private static final String ATTR_NAME = "__CURRENT_TRACE_HANDLER_TRACE_ATTR___";
|
||||
|
||||
private final Tracer tracer;
|
||||
|
||||
private final UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||
|
||||
public TraceHandlerInterceptor(Tracer tracer) {
|
||||
this.tracer = tracer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
// TODO: get trace data from request?
|
||||
// TODO: what is the description?
|
||||
String uri = this.urlPathHelper.getPathWithinApplication(request);
|
||||
String spanName = "http:" + uri;
|
||||
Span span = this.tracer.startTrace(spanName);
|
||||
request.setAttribute(ATTR_NAME, span);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler, ModelAndView modelAndView) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler, Exception ex) throws Exception {
|
||||
Span span = Span.class.cast(request.getAttribute(ATTR_NAME));
|
||||
this.tracer.close(span);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ import org.springframework.cloud.sleuth.instrument.async.TraceContinuingCallable
|
||||
import org.springframework.web.context.request.async.WebAsyncTask;
|
||||
|
||||
/**
|
||||
* Aspect that adds correlation id to
|
||||
* Aspect that adds tracing to
|
||||
* <p/>
|
||||
* <ul>
|
||||
* <li>{@link org.springframework.web.bind.annotation.RestController} annotated classes
|
||||
@@ -51,17 +51,19 @@ import org.springframework.web.context.request.async.WebAsyncTask;
|
||||
* a new span - since the one in TraceFilter will wait until processing has been
|
||||
* finished
|
||||
*
|
||||
* @author Tomasz Nurkewicz, 4financeIT
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see org.springframework.web.bind.annotation.RestController
|
||||
* @see org.springframework.stereotype.Controller
|
||||
* @see org.springframework.web.client.RestOperations
|
||||
* @see org.springframework.cloud.sleuth.TraceCallable
|
||||
* @see org.springframework.cloud.sleuth.Tracer
|
||||
* @see org.springframework.cloud.sleuth.instrument.web.TraceFilter
|
||||
*
|
||||
* @author Tomasz Nurkewicz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Aspect
|
||||
public class TraceWebAspect {
|
||||
|
||||
@@ -37,12 +37,15 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Registers beans that add tracing to requests
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enables tracing to HTTP requests.
|
||||
*
|
||||
* @author Tomasz Nurkewicz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Michal Chmielarz, 4financeIT
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.sleuth.web.enabled", matchIfMissing = true)
|
||||
|
||||
@@ -31,6 +31,8 @@ import org.springframework.util.StringUtils;
|
||||
* to enrich the request headers with trace related information.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
abstract class AbstractTraceHttpRequestInterceptor
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
@@ -35,7 +35,9 @@ import feign.Target;
|
||||
import static feign.Util.checkNotNull;
|
||||
|
||||
/**
|
||||
* Wraps execution in Sleuth's TraceCommand
|
||||
* Wraps {@link HystrixCommand} execution in Sleuth's {@link TraceCommand}
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class SleuthHystrixInvocationHandler implements InvocationHandler {
|
||||
|
||||
@@ -59,7 +61,6 @@ final class SleuthHystrixInvocationHandler implements InvocationHandler {
|
||||
HystrixCommand.Setter setter = HystrixCommand.Setter
|
||||
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
|
||||
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey));
|
||||
|
||||
HystrixCommand<Object> hystrixCommand = new TraceCommand<Object>(this.tracer, this.traceKeys,
|
||||
setter) {
|
||||
@Override public Object doRun() throws Exception {
|
||||
@@ -73,7 +74,6 @@ final class SleuthHystrixInvocationHandler implements InvocationHandler {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
if (HystrixCommand.class.isAssignableFrom(method.getReturnType())) {
|
||||
return hystrixCommand;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceAsyncClientHttpRequestFactoryWrapper extends AbstractTraceHttpRequestInterceptor
|
||||
implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory {
|
||||
@@ -45,7 +47,7 @@ public class TraceAsyncClientHttpRequestFactoryWrapper extends AbstractTraceHttp
|
||||
private final ClientHttpRequestFactory syncDelegate;
|
||||
|
||||
/**
|
||||
* According to the javadocs all Spring {@link AsyncClientHttpRequestFactory} implement
|
||||
* According to the JavaDocs all Spring {@link AsyncClientHttpRequestFactory} implement
|
||||
* the {@link ClientHttpRequestFactory} interface.
|
||||
*
|
||||
* In case that it's not true we're setting the {@link SimpleClientHttpRequestFactory}
|
||||
|
||||
@@ -26,6 +26,11 @@ import org.springframework.util.concurrent.ListenableFuture;
|
||||
/**
|
||||
* AsyncListenableTaskExecutor that wraps all Runnable / Callable tasks into
|
||||
* their trace related representation
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see Tracer#wrap(Runnable)
|
||||
* @see Tracer#wrap(Callable)
|
||||
*/
|
||||
public class TraceAsyncListenableTaskExecutor implements AsyncListenableTaskExecutor {
|
||||
|
||||
|
||||
@@ -63,10 +63,12 @@ import feign.codec.Decoder;
|
||||
import feign.hystrix.HystrixFeign;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enables span information propagation when using Feign.
|
||||
*
|
||||
* Configuration for ensuring that Spans are propagated while using Feign
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.sleuth.feign.enabled", matchIfMissing = true)
|
||||
|
||||
@@ -24,8 +24,13 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
/**
|
||||
* Implementation of {@link ClientHttpResponse} that upon
|
||||
* {@link ClientHttpResponse#close() closing the response}
|
||||
* {@link TraceRestTemplateInterceptor#finish() closes the span}
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceHttpResponse implements ClientHttpResponse {
|
||||
|
||||
|
||||
@@ -27,11 +27,13 @@ import org.springframework.http.client.ClientHttpResponse;
|
||||
* Interceptor that verifies whether the trance and span id has been set on the request
|
||||
* and sets them if one or both of them are missing.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @see org.springframework.web.client.RestTemplate
|
||||
* @see SpanAccessor
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Spencer Gibb
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceRestTemplateInterceptor extends AbstractTraceHttpRequestInterceptor
|
||||
implements ClientHttpRequestInterceptor {
|
||||
|
||||
@@ -30,7 +30,13 @@ import org.springframework.http.client.AsyncClientHttpRequestFactory;
|
||||
import org.springframework.web.client.AsyncRestTemplate;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enables span information propagation for {@link AsyncClientHttpRequestFactory} and
|
||||
* {@link AsyncRestTemplate}
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.sleuth.async.client.enabled", matchIfMissing = true)
|
||||
|
||||
@@ -36,7 +36,12 @@ import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enables span information propagation when using {@link RestTemplate}
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.sleuth.client.enabled", matchIfMissing = true)
|
||||
|
||||
@@ -26,8 +26,11 @@ import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
|
||||
/**
|
||||
* A post request {@link ZuulFilter} that publishes an event upon start of the filtering
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TracePostZuulFilter extends ZuulFilter
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
@@ -25,14 +25,18 @@ import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
import com.netflix.zuul.context.RequestContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A pre request {@link ZuulFilter} that sets tracing related headers on the request
|
||||
* from the current span. We're doing so to ensure tracing propagates to the next hop.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TracePreZuulFilter extends ZuulFilter
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
@@ -19,8 +19,6 @@ package org.springframework.cloud.sleuth.instrument.zuul;
|
||||
import java.io.InputStream;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import com.netflix.client.http.HttpRequest;
|
||||
import com.netflix.niws.client.http.RestClient;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
@@ -35,8 +33,15 @@ import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import com.netflix.client.http.HttpRequest;
|
||||
import com.netflix.niws.client.http.RestClient;
|
||||
|
||||
/**
|
||||
* Propagates traces downstream via http headers that contain trace metadata.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommandFactory
|
||||
implements ApplicationEventPublisherAware {
|
||||
@@ -104,8 +109,10 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
|
||||
setHeader(requestBuilder, Span.TRACE_ID_NAME, Span.idToHex(span.getTraceId()));
|
||||
setHeader(requestBuilder, Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
|
||||
setHeader(requestBuilder, Span.SPAN_NAME_NAME, span.getName());
|
||||
setHeader(requestBuilder, Span.PARENT_ID_NAME,
|
||||
Span.idToHex(getParentId(span)));
|
||||
if (getParentId(span) != null) {
|
||||
setHeader(requestBuilder, Span.PARENT_ID_NAME,
|
||||
Span.idToHex(getParentId(span)));
|
||||
}
|
||||
setHeader(requestBuilder, Span.PROCESS_ID_NAME,
|
||||
span.getProcessId());
|
||||
publish(new ClientSentEvent(this, span));
|
||||
|
||||
@@ -31,9 +31,12 @@ import org.springframework.context.annotation.Configuration;
|
||||
import com.netflix.zuul.ZuulFilter;
|
||||
|
||||
/**
|
||||
* Registers beans that add tracing to requests
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enables span information propagation when using Zuul.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.sleuth.zuul.enabled", matchIfMissing = true)
|
||||
|
||||
@@ -28,7 +28,14 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enables a {@link Slf4jSpanListener} that prints tracing information in the logs.
|
||||
* <p>
|
||||
* Note: this is only available for Slf4j
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean(Tracer.class)
|
||||
|
||||
@@ -29,7 +29,12 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
/**
|
||||
* Span listener that logs to the console when a span got
|
||||
* started / stopped / continued.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class Slf4jSpanListener {
|
||||
|
||||
|
||||
@@ -4,8 +4,11 @@ import org.springframework.boot.actuate.metrics.CounterService;
|
||||
|
||||
/**
|
||||
* Service to operate on accepted and dropped spans statistics.
|
||||
* Operates on a {@link CounterService} underneath
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class CounterServiceBasedSpanReporterService implements SpanReporterService {
|
||||
private final String acceptedSpansMetricName;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package org.springframework.cloud.sleuth.metric;
|
||||
|
||||
/**
|
||||
* Span reporting service that does nothing
|
||||
* {@link SpanReporterService} that does nothing
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class NoOpSpanReporterService implements SpanReporterService {
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* Configuration properties for Sleuth related metrics
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.sleuth.metric")
|
||||
public class SleuthMetricProperties {
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package org.springframework.cloud.sleuth.metric;
|
||||
|
||||
/**
|
||||
* Contract for a service that measures the number of accepted / dropped spans.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface SpanReporterService {
|
||||
|
||||
/**
|
||||
* Called when spans are submitted to SpanCollector for processing.
|
||||
* Called when spans are submitted to span collector for processing.
|
||||
*
|
||||
* @param quantity the number of spans accepted.
|
||||
*/
|
||||
|
||||
@@ -27,7 +27,12 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enables Sleuth related metrics reporting
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value="spring.sleuth.metrics.enabled", matchIfMissing=true)
|
||||
|
||||
@@ -20,7 +20,11 @@ import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* {@link Sampler} that traces each action
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class AlwaysSampler implements Sampler {
|
||||
@Override
|
||||
|
||||
@@ -21,14 +21,19 @@ import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
|
||||
/**
|
||||
* {@link Sampler} that traces only if there is already some tracing going on.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see SpanAccessor#isTracing()
|
||||
*/
|
||||
public class IsTracingSampler implements Sampler {
|
||||
|
||||
private SpanAccessor accessor;
|
||||
|
||||
public IsTracingSampler(SpanAccessor accessor) {
|
||||
super();
|
||||
this.accessor = accessor;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,11 @@ import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* {@link Sampler} that never traces
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class NeverSampler implements Sampler {
|
||||
|
||||
|
||||
@@ -5,12 +5,15 @@ import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* Sampler that based on the given percentage rate will allow sampling.
|
||||
* <p>
|
||||
*
|
||||
* A couple of assumptions have to take place in order for the algorithm to work properly:
|
||||
* <p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>We're taking the TraceID into consideration for sampling to be consistent</li>
|
||||
* <li>We apply the Zipkin algorithm to define whether we should sample or not (we're comparing against thresholdg) - https://github.com/openzipkin/zipkin-java/blob/master/zipkin/src/main/java/zipkin/Sampler.java</li>
|
||||
* <li>We apply the Zipkin algorithm to define whether we should sample or not (we're comparing against threshold)
|
||||
* - https://github.com/openzipkin/zipkin-java/blob/master/zipkin/src/main/java/zipkin/Sampler.java</li>
|
||||
* </ul>
|
||||
*
|
||||
* The value provided from SamplerConfiguration in terms of percentage is an estimation. It might occur that amount
|
||||
@@ -18,6 +21,8 @@ import org.springframework.cloud.sleuth.Span;
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Adrian Cole
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class PercentageBasedSampler implements Sampler {
|
||||
|
||||
|
||||
@@ -3,8 +3,12 @@ package org.springframework.cloud.sleuth.sampler;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties related to sampling
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Adrian Cole
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.sleuth.sampler")
|
||||
public class SamplerProperties {
|
||||
|
||||
@@ -32,7 +32,11 @@ import org.springframework.cloud.sleuth.util.ExceptionUtils;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link Tracer}
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DefaultTracer implements Tracer {
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ import org.springframework.core.NamedThreadLocal;
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class SpanContextHolder {
|
||||
|
||||
|
||||
@@ -19,13 +19,25 @@ package org.springframework.cloud.sleuth.util;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
/**
|
||||
* Utility class for logging exceptions. Useful for test purposes -
|
||||
* when a warning message should be presented an exception can be thrown.
|
||||
* <p>
|
||||
* The purpose of this class is not to throw exceptions from the user's code
|
||||
* when there are some issues with tracing.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public abstract class ExceptionUtils {
|
||||
public final class ExceptionUtils {
|
||||
private static final Log log = org.apache.commons.logging.LogFactory
|
||||
.getLog(ExceptionUtils.class);
|
||||
private static boolean fail = false;
|
||||
|
||||
private ExceptionUtils() {
|
||||
throw new IllegalStateException("Utility class can't be instantiated");
|
||||
}
|
||||
|
||||
public static void warn(String msg) {
|
||||
if (fail) {
|
||||
throw new IllegalStateException(msg);
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DiscoveryClientHostLocator implements HostLocator {
|
||||
|
||||
|
||||
@@ -23,8 +23,11 @@ import java.nio.ByteBuffer;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
/**
|
||||
* Represents the host from which the span was sent
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class Host {
|
||||
|
||||
@@ -19,11 +19,12 @@ package org.springframework.cloud.sleuth.stream;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
|
||||
/**
|
||||
* Strategy for locating a "host" from a Spring Cloud Span (and whatever other
|
||||
* Strategy for locating a {@link Host "host"} from a Spring Cloud Span (and whatever other
|
||||
* environment properties might be available).
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface HostLocator {
|
||||
|
||||
|
||||
@@ -23,8 +23,17 @@ import org.springframework.context.event.EventListener;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link HostLocator} that retrieves:
|
||||
*
|
||||
* <ul>
|
||||
* <li><b>service name</b> - either from {@link span#getProcessId()} or current application name</li>
|
||||
* <li><b>address</b> - from {@link ServerProperties}</li>
|
||||
* <li><b>port</b> - from lazily assigned port or {@link ServerProperties}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ServerPropertiesHostLocator implements HostLocator {
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.springframework.messaging.SubscribableChannel;
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface SleuthSink {
|
||||
|
||||
|
||||
@@ -21,14 +21,15 @@ import org.springframework.messaging.MessageChannel;
|
||||
|
||||
/**
|
||||
* Defines a message channel for instrumented applications to use to send span data to a
|
||||
* message broker. The channel accepts data in the form of {@link Spans} to buffer
|
||||
* multiple actual Span instances in a single message. A client app may occasionally drop
|
||||
* message broker. The channel accepts data in the form of {@link spans} to buffer
|
||||
* multiple actual span instances in a single message. A client app may occasionally drop
|
||||
* spans, and if it does it should attempt to account for and report the number dropped.
|
||||
*
|
||||
* @see SleuthSink
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see SleuthSink
|
||||
*/
|
||||
public interface SleuthSource {
|
||||
|
||||
|
||||
@@ -44,12 +44,15 @@ import org.springframework.messaging.support.ChannelInterceptor;
|
||||
import org.springframework.messaging.support.ChannelInterceptorAdapter;
|
||||
|
||||
/**
|
||||
* Autoconfiguration for sending Spans over Spring Cloud Stream. This is for the producer
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* for sending spans over Spring Cloud Stream. This is for the producer
|
||||
* (via {@link SleuthSource}). A consumer can enable binding to {@link SleuthSink} and
|
||||
* receive the messages coming from the source (they have the same channel name so there
|
||||
* is no additional configuration to do by default).
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({SleuthStreamProperties.class, SamplerProperties.class})
|
||||
|
||||
@@ -19,7 +19,11 @@ package org.springframework.cloud.sleuth.stream;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties related to Sleuth Stream
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.sleuth.stream")
|
||||
public class SleuthStreamProperties {
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
|
||||
public class Spans {
|
||||
|
||||
@@ -37,8 +37,12 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
|
||||
/**
|
||||
* {@link EnvironmentPostProcessor} that sets the default properties for
|
||||
* Sleuth Stream.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class StreamEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ import org.springframework.integration.annotation.MessageEndpoint;
|
||||
* A message source for spans. Also handles RPC flavoured annotations.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@MessageEndpoint
|
||||
public class StreamSpanListener {
|
||||
|
||||
@@ -25,6 +25,16 @@ import org.springframework.context.annotation.Import;
|
||||
|
||||
import zipkin.server.EnableZipkinServer;
|
||||
|
||||
/**
|
||||
* When enabled, instrumented apps will transport spans over a
|
||||
* Spring Cloud Stream, for example RabbitMQ.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see ZipkinMessageListener
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
|
||||
@@ -32,6 +32,10 @@ import zipkin.Span.Builder;
|
||||
|
||||
/**
|
||||
* This converts sleuth spans to zipkin ones, skipping invalid or unsampled.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
final class SamplingZipkinSpanIterator implements Iterator<zipkin.Span> {
|
||||
|
||||
|
||||
@@ -40,6 +40,16 @@ import zipkin.Sampler;
|
||||
import zipkin.Span.Builder;
|
||||
import zipkin.SpanStore;
|
||||
|
||||
/**
|
||||
* A message listener that is turned on if Sleuth Stream is disabled.
|
||||
* Asynchronously stores the received spans in a {@link SpanStore}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @see NotSleuthStreamClient
|
||||
*/
|
||||
@MessageEndpoint
|
||||
@Conditional(NotSleuthStreamClient.class)
|
||||
public class ZipkinMessageListener {
|
||||
@@ -77,9 +87,7 @@ public class ZipkinMessageListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of Annotations that are present in sleuth Span object.
|
||||
*
|
||||
* @return list of Annotations that could be added to Zipkin Span.
|
||||
* Adds binary annotations from the sleuth Span
|
||||
*/
|
||||
static void addZipkinBinaryAnnotations(Builder zipkinSpan, Span span,
|
||||
Endpoint endpoint) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import zipkin.Endpoint;
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class DiscoveryClientEndpointLocator implements EndpointLocator {
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import zipkin.Endpoint;
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface EndpointLocator {
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import zipkin.Endpoint;
|
||||
/**
|
||||
* Endpoint locator that will try to call an endpoint via Discovery Client
|
||||
* and will fallback to Server Properties if an exception is thrown
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class FallbackHavingEndpointLocator implements EndpointLocator {
|
||||
|
||||
|
||||
@@ -25,6 +25,10 @@ import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
/**
|
||||
* Submits spans using Zipkin's {@code POST /spans} endpoint.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public final class HttpZipkinSpanReporter
|
||||
implements ZipkinSpanReporter, Flushable, Closeable {
|
||||
|
||||
@@ -24,8 +24,16 @@ import org.springframework.context.event.EventListener;
|
||||
import zipkin.Endpoint;
|
||||
|
||||
/**
|
||||
* {@link EndpointLocator} implementation that:
|
||||
*
|
||||
* <ul>
|
||||
* <li><b>address</b> - from {@link ServerProperties}</li>
|
||||
* <li><b>port</b> - from lazily assigned port or {@link ServerProperties}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ServerPropertiesEndpointLocator implements EndpointLocator {
|
||||
|
||||
|
||||
@@ -36,7 +36,13 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enables reporting to Zipkin via HTTP. Has a default {@link Sampler} set as
|
||||
* {@link PercentageBasedSampler}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({ZipkinProperties.class, SamplerProperties.class})
|
||||
|
||||
@@ -19,7 +19,11 @@ package org.springframework.cloud.sleuth.zipkin;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Zipkin settings
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@ConfigurationProperties("spring.zipkin")
|
||||
public class ZipkinProperties {
|
||||
|
||||
@@ -37,7 +37,11 @@ import zipkin.Constants;
|
||||
import zipkin.Endpoint;
|
||||
|
||||
/**
|
||||
* Listener of Sleuth events. Reports to Zipkin via {@link ZipkinSpanReporter}.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ZipkinSpanListener {
|
||||
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
|
||||
@@ -171,9 +175,7 @@ public class ZipkinSpanListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of Annotations that are present in sleuth Span object.
|
||||
*
|
||||
* @return list of Annotations that could be added to Zipkin Span.
|
||||
* Adds binary annotation from the sleuth Span
|
||||
*/
|
||||
private void addZipkinBinaryAnnotations(zipkin.Span.Builder zipkinSpan,
|
||||
Span span, Endpoint endpoint) {
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
package org.springframework.cloud.sleuth.zipkin;
|
||||
|
||||
/**
|
||||
* Contract for reporting Zipkin spans to Zipkin.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface ZipkinSpanReporter {
|
||||
/**
|
||||
* Receives completed spans from {@link ZipkinSpanListener} and submits them to a Zipkin
|
||||
|
||||
@@ -23,14 +23,14 @@ public class HttpZipkinSpanReporterTest {
|
||||
HttpZipkinSpanReporter reporter = new HttpZipkinSpanReporter(
|
||||
this.zipkin.httpUrl(), 0, this.spanReporterService);
|
||||
|
||||
@Test
|
||||
@Test
|
||||
public void reportDoesntDoIO() throws Exception {
|
||||
this.reporter.report(span(1L, "foo"));
|
||||
|
||||
assertThat(this.zipkin.httpRequestCount()).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test
|
||||
public void reportIncrementsAcceptedMetrics() throws Exception {
|
||||
this.reporter.report(span(1L, "foo"));
|
||||
|
||||
@@ -38,7 +38,7 @@ public class HttpZipkinSpanReporterTest {
|
||||
assertThat(this.inMemorySpanCounter.getDroppedSpans()).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test
|
||||
public void dropsWhenQueueIsFull() throws Exception {
|
||||
for (int i = 0; i < 1001; i++)
|
||||
this.reporter.report(span(1L, "foo"));
|
||||
@@ -63,7 +63,7 @@ public class HttpZipkinSpanReporterTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test
|
||||
public void incrementsDroppedSpansWhenServerErrors() throws Exception {
|
||||
this.zipkin.enqueueFailure(HttpFailure.sendErrorResponse(500, "Ouch"));
|
||||
|
||||
@@ -75,7 +75,7 @@ public class HttpZipkinSpanReporterTest {
|
||||
assertThat(this.inMemorySpanCounter.getDroppedSpans()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test
|
||||
public void incrementsDroppedSpansWhenServerDisconnects() throws Exception {
|
||||
this.zipkin.enqueueFailure(HttpFailure.disconnectDuringBody());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user