[#69] Added javadocs

fixes #69
This commit is contained in:
Marcin Grzejszczak
2016-02-23 21:16:02 +01:00
committed by Marcin Grzejszczak
parent be1b986bec
commit 3000a4f37d
98 changed files with 539 additions and 221 deletions

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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)

View File

@@ -23,6 +23,7 @@ package org.springframework.cloud.sleuth;
* the name of the span.
*
* @author Marcin Grzejszczak
* @since 1.0.0
*/
public interface SpanNamer {

View File

@@ -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> {

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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<>();

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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")

View File

@@ -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;

View File

@@ -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")

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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

View File

@@ -25,7 +25,7 @@ import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
/**
* @author Dave Syer
*
* @since 1.0.0
*/
public class LazyTraceAsyncCustomizer extends AsyncConfigurerSupport {

View File

@@ -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 {

View File

@@ -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> {

View File

@@ -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 {

View File

@@ -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
*/

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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";

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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)

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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}

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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));

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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.
*/

View File

@@ -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)

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -25,6 +25,8 @@ import org.springframework.core.NamedThreadLocal;
*
* @author Spencer Gibb
* @author Dave Syer
*
* @since 1.0.0
*/
class SpanContextHolder {

View File

@@ -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);

View File

@@ -29,6 +29,7 @@ import org.springframework.util.Assert;
*
* @author Dave Syer
*
* @since 1.0.0
*/
public class DiscoveryClientHostLocator implements HostLocator {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -28,6 +28,7 @@ import org.springframework.messaging.SubscribableChannel;
*
* @author Dave Syer
*
* @since 1.0.0
*/
public interface SleuthSink {

View File

@@ -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 {

View File

@@ -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})

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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> {

View File

@@ -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) {

View File

@@ -28,6 +28,7 @@ import zipkin.Endpoint;
*
* @author Dave Syer
*
* @since 1.0.0
*/
public class DiscoveryClientEndpointLocator implements EndpointLocator {

View File

@@ -23,6 +23,7 @@ import zipkin.Endpoint;
*
* @author Dave Syer
*
* @since 1.0.0
*/
public interface EndpointLocator {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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})

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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

View File

@@ -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());