diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..323872eea --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +root=true + +[*.java] +indent_style = tab +indent_size = 4 +continuation_indent_size = 8 + +[*.groovy] +indent_style = tab +indent_size = 4 +continuation_indent_size = 8 + +[*.xml] +indent_style = tab +indent_size = 4 +continuation_indent_size = 8 \ No newline at end of file diff --git a/.springformat b/.springformat new file mode 100644 index 000000000..e69de29bb diff --git a/pom.xml b/pom.xml index 9d9c9869b..4cd626149 100644 --- a/pom.xml +++ b/pom.xml @@ -115,6 +115,10 @@ org.apache.maven.plugins maven-checkstyle-plugin + + io.spring.javaformat + spring-javaformat-maven-plugin + diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultSpanNamer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultSpanNamer.java index a902a9faf..1bbfc9ddb 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultSpanNamer.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/DefaultSpanNamer.java @@ -23,17 +23,24 @@ import org.springframework.core.annotation.AnnotationUtils; /** * Default implementation of SpanNamer that tries to get the span name as follows: * - *
  • - * - * - * - * + *
  • + * + * + * + * *
  • * * @author Marcin Grzejszczak * @since 1.0.0 - * * @see SpanName */ public class DefaultSpanNamer implements SpanNamer { @@ -53,15 +60,15 @@ public class DefaultSpanNamer implements SpanNamer { if (o instanceof Method) { return AnnotationUtils.findAnnotation((Method) o, SpanName.class); } - return AnnotationUtils - .findAnnotation(o.getClass(), SpanName.class); + return AnnotationUtils.findAnnotation(o.getClass(), SpanName.class); } private static boolean isDefaultToString(Object delegate, String spanName) { if (delegate instanceof Method) { return delegate.toString().equals(spanName); } - return (delegate.getClass().getName() + "@" + - Integer.toHexString(delegate.hashCode())).equals(spanName); + return (delegate.getClass().getName() + "@" + + Integer.toHexString(delegate.hashCode())).equals(spanName); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanAdjuster.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanAdjuster.java index e3a833a5b..72eb3ba21 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanAdjuster.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanAdjuster.java @@ -19,19 +19,27 @@ package org.springframework.cloud.sleuth; import zipkin2.Span; /** + * Deprecated Span Adjuster. + * * @deprecated use {@link brave.handler.FinishedSpanHandler} + * @author Marcin Grzejszczak */ @Deprecated public interface SpanAdjuster { + /** - * You can adjust the {@link zipkin2.Span} by creating a new one using the {@link Span#toBuilder()} - * before reporting it. + * You can adjust the {@link zipkin2.Span} by creating a new one using the + * {@link Span#toBuilder()} before reporting it. * - * With the legacy Sleuth approach we're generating spans with a fixed name. Some users want to modify the name - * depending on some values of tags. Implementation of this interface can be used to alter - * then name. Example: + * With the legacy Sleuth approach we're generating spans with a fixed name. Some + * users want to modify the name depending on some values of tags. Implementation of + * this interface can be used to alter then name. Example: * * {@code span -> span.toBuilder().name(scrub(span.getName())).build();} + * + * @param - span to adjust + * @return - adjusted span */ Span adjust(Span span); -} \ No newline at end of file + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanName.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanName.java index 78115f22f..c45a1d983 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanName.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanName.java @@ -23,16 +23,15 @@ 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 Runnable Runnable} or {@link java.util.concurrent.Callable Callable} classes - * for the instrumentation logic to pick up how to name the span. + * Annotation to provide the name for the span. You should annotate all your custom + * {@link Runnable Runnable} or {@link java.util.concurrent.Callable Callable} classes for + * the instrumentation logic to pick up how to name the span. *

    * - * Having for example the following code - *

    {@code
    - *     @SpanName("custom-operation")
    + * Having for example the following code 
    {@code
    + *     @SpanName("custom-operation")
      *     class CustomRunnable implements Runnable {
    - *         @Override
    + *         @Override
      *         public void run() {
      *          // latency of this method will be recorded in a span named "custom-operation"
      *         }
    @@ -42,21 +41,21 @@ import java.lang.annotation.Target;
      * Will result in creating a span with name {@code custom-operation}.
      * 

    * - * When there's no @SpanName annotation, {@code toString} is used. Here's an - * example of the above, but via an anonymous instance. - *

    {@code
    + * When there's no @SpanName annotation, {@code toString} is used. Here's an example of
    + * the above, but via an anonymous instance. 
    {@code
      *     return new Runnable() {
      *          -- snip --
      *
    - *          @Override
    + *          @Override
      *          public String toString() {
      *              return "custom-operation";
      *          }
      *     };
      * }
    * - * Starting with version {@code 1.3.0} you can also put the annotation on an {@link org.springframework.scheduling.annotation.Async} - * annotated method and the value of that annotation will be used as the span name. + * Starting with version {@code 1.3.0} you can also put the annotation on an + * {@link org.springframework.scheduling.annotation.Async} annotated method and the value + * of that annotation will be used as the span name. * * @author Marcin Grzejszczak * @since 1.0.0 @@ -65,8 +64,11 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SpanName { + /** - * Name of the span to be resolved at runtime + * Name of the span to be resolved at runtime. + * @return - value of the span name. */ String value(); + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanNamer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanNamer.java index 53ec24365..1a5bd93e4 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanNamer.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanNamer.java @@ -17,10 +17,9 @@ package org.springframework.cloud.sleuth; /** - * Describes how for a given object a span should be named. In the vast majority - * of cases a name should be provided explicitly. In case of instrumentation - * where the name has to be resolved at runtime this interface will provide - * the name of the span. + * Describes how for a given object a span should be named. In the vast majority of cases + * a name should be provided explicitly. In case of instrumentation where the name has to + * be resolved at runtime this interface will provide the name of the span. * * @author Marcin Grzejszczak * @since 1.0.0 @@ -29,10 +28,11 @@ public interface SpanNamer { /** * Retrieves the span name for the given object. - * * @param object - object for which span name should be picked - * @param defaultValue - the default valued to be returned if span name can't be calculated + * @param defaultValue - the default valued to be returned if span name can't be + * calculated * @return span name */ String name(Object object, String defaultValue); + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/AbstractSleuthMethodInvocationProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/AbstractSleuthMethodInvocationProcessor.java index dc956f40a..a6ca43ac1 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/AbstractSleuthMethodInvocationProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/AbstractSleuthMethodInvocationProcessor.java @@ -26,18 +26,26 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; /** + * Sleuth annotation processor + * * @author Marcin Grzejszczak */ abstract class AbstractSleuthMethodInvocationProcessor implements SleuthMethodInvocationProcessor, BeanFactoryAware { + private static final Log logger = LogFactory .getLog(AbstractSleuthMethodInvocationProcessor.class); + private static final String CLASS_KEY = "class"; + private static final String METHOD_KEY = "method"; BeanFactory beanFactory; + private NewSpanParser newSpanParser; + private Tracer tracer; + private SpanTagAnnotationHandler spanTagAnnotationHandler; void before(MethodInvocation invocation, Span span, String log, boolean hasLog) { @@ -111,7 +119,9 @@ abstract class AbstractSleuthMethodInvocationProcessor return this.spanTagAnnotationHandler; } - @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/ContinueSpan.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/ContinueSpan.java index a1c183a04..8b36b7877 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/ContinueSpan.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/ContinueSpan.java @@ -23,20 +23,25 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Tells Sleuth that all Sleuth related annotations should be applied - * to an existing span instead of creating a new one. + * Tells Sleuth that all Sleuth related annotations should be applied to an existing span + * instead of creating a new one. * * @author Marcin Grzejszczak * @since 1.2.0 */ @Retention(RetentionPolicy.RUNTIME) @Inherited -@Target(value = { ElementType.METHOD }) +@Target(value = { + ElementType.METHOD +}) public @interface ContinueSpan { /** - * The value passed to the annotation will be used and the framework - * will create two events with the {@code .start} and {@code .end} suffixes + * Log statement to be appended to the span. + * + * @return - the value passed to the annotation will be used and the framework will create two + * events with the {@code .start} and {@code .end} suffixes. */ String log() default ""; + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/DefaultSpanCreator.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/DefaultSpanCreator.java index e2dd913ba..090948144 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/DefaultSpanCreator.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/DefaultSpanCreator.java @@ -23,24 +23,24 @@ import org.springframework.cloud.sleuth.util.SpanNameUtil; import org.springframework.util.StringUtils; /** - * Default implementation of the {@link NewSpanParser} that parses only the - * span name. + * Default implementation of the {@link NewSpanParser} that parses only the span name. * * @author Christian Schwerdtfeger * @since 1.2.0 */ -class DefaultNewSpanParser implements NewSpanParser { +class DefaultSpanCreator implements NewSpanParser { - private static final Log log = LogFactory.getLog(DefaultNewSpanParser.class); + private static final Log log = LogFactory.getLog(DefaultSpanCreator.class); @Override public void parse(MethodInvocation pjp, NewSpan newSpan, SpanCustomizer span) { - String name = newSpan == null || StringUtils.isEmpty(newSpan.name()) ? - pjp.getMethod().getName() : newSpan.name(); + String name = newSpan == null || StringUtils.isEmpty(newSpan.name()) + ? pjp.getMethod().getName() : newSpan.name(); String changedName = SpanNameUtil.toLowerHyphen(name); if (log.isDebugEnabled()) { - log.debug("For the class [" + pjp.getThis().getClass() + "] method " - + "[" + pjp.getMethod().getName() + "] will name the span [" + changedName + "]"); + log.debug("For the class [" + pjp.getThis().getClass() + "] method " + "[" + + pjp.getMethod().getName() + "] will name the span [" + changedName + + "]"); } span.name(changedName); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NewSpan.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NewSpan.java index 34a060dc8..af5e215bf 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NewSpan.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NewSpan.java @@ -24,13 +24,13 @@ import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; /** - * Allows to create a new span around a public method. The new span - * will be either a child of an existing span if a trace is already in progress - * or a new span will be created if there was no previous trace. + * Allows to create a new span around a public method. The new span will be either a child + * of an existing span if a trace is already in progress or a new span will be created if + * there was no previous trace. *

    - * Method parameters can be annotated with {@link SpanTag}, which will end - * in adding the parameter value as a tag value to the span. The tag key will be - * the value of the {@code key} annotation from {@link SpanTag}. + * Method parameters can be annotated with {@link SpanTag}, which will end in adding the + * parameter value as a tag value to the span. The tag key will be the value of the + * {@code key} annotation from {@link SpanTag}. * * * @author Christian Schwerdtfeger @@ -38,17 +38,21 @@ import org.springframework.core.annotation.AliasFor; */ @Retention(RetentionPolicy.RUNTIME) @Inherited -@Target(value = { ElementType.METHOD }) +@Target(value = { + ElementType.METHOD +}) public @interface NewSpan { /** - * The name of the span which will be created. Default is the annotated method's name separated by hyphens. + * @return - The name of the span which will be created. Default is the annotated method's name + * separated by hyphens. */ @AliasFor("value") String name() default ""; /** - * The name of the span which will be created. Default is the annotated method's name separated by hyphens. + * @return - The name of the span which will be created. Default is the annotated method's name + * separated by hyphens. */ @AliasFor("name") String value() default ""; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NewSpanParser.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NewSpanParser.java index 91a31a60b..68d93fc0f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NewSpanParser.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NewSpanParser.java @@ -27,6 +27,13 @@ import org.aopalliance.intercept.MethodInvocation; */ public interface NewSpanParser { - /** Override to control the name and tags on an annotation-based span */ + /** + * Override to control the name and tags on an annotation-based span. + * + * @param methodInvocation + * @param newSpan + * @param span + */ void parse(MethodInvocation methodInvocation, NewSpan newSpan, SpanCustomizer span); + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NoOpTagValueResolver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NoOpTagValueResolver.java index e33267f31..603d47589 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NoOpTagValueResolver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NoOpTagValueResolver.java @@ -17,13 +17,16 @@ package org.springframework.cloud.sleuth.annotation; /** - * Does nothing + * Does nothing. * * @author Marcin Grzejszczak * @since 1.2.0 */ class NoOpTagValueResolver implements TagValueResolver { - @Override public String resolve(Object parameter) { + + @Override + public String resolve(Object parameter) { return null; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NonReactorSleuthMethodInvocationProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NonReactorSleuthMethodInvocationProcessor.java index 09074c0c3..9e5382fe8 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NonReactorSleuthMethodInvocationProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/NonReactorSleuthMethodInvocationProcessor.java @@ -22,20 +22,25 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.util.StringUtils; /** + * Method Invocation processor for non reactor apps. + * * @author Marcin Grzejszczak * @since 2.1.0 */ -class NonReactorSleuthMethodInvocationProcessor extends AbstractSleuthMethodInvocationProcessor { +class NonReactorSleuthMethodInvocationProcessor + extends AbstractSleuthMethodInvocationProcessor { - @Override public Object process(MethodInvocation invocation, NewSpan newSpan, - ContinueSpan continueSpan) throws Throwable { + @Override + public Object process(MethodInvocation invocation, NewSpan newSpan, + ContinueSpan continueSpan) throws Throwable { return proceedUnderSynchronousSpan(invocation, newSpan, continueSpan); } - private Object proceedUnderSynchronousSpan( - MethodInvocation invocation, NewSpan newSpan, ContinueSpan continueSpan) throws Throwable { + private Object proceedUnderSynchronousSpan(MethodInvocation invocation, + NewSpan newSpan, ContinueSpan continueSpan) throws Throwable { Span span = tracer().currentSpan(); - //in case of @ContinueSpan and no span in tracer we start new span and should close it on completion + // in case of @ContinueSpan and no span in tracer we start new span and should + // close it on completion boolean startNewSpan = newSpan != null || span == null; if (startNewSpan) { span = tracer().nextSpan(); @@ -47,11 +52,14 @@ class NonReactorSleuthMethodInvocationProcessor extends AbstractSleuthMethodInvo try (Tracer.SpanInScope ws = tracer().withSpanInScope(span)) { before(invocation, span, log, hasLog); return invocation.proceed(); - } catch (Exception e) { - onFailure(span, log, hasLog, e); - throw e; - } finally { + } + catch (Exception ex) { + onFailure(span, log, hasLog, ex); + throw ex; + } + finally { after(span, startNewSpan, log, hasLog); } } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/ReactorSleuthMethodInvocationProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/ReactorSleuthMethodInvocationProcessor.java index c1f105cf5..1c2fa7c9f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/ReactorSleuthMethodInvocationProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/ReactorSleuthMethodInvocationProcessor.java @@ -30,39 +30,46 @@ import reactor.core.publisher.Mono; import reactor.core.publisher.SignalType; /** + * Method Invocation Processor for Reactor. + * * @author Marcin Grzejszczak * @since 2.1.0 */ -class ReactorSleuthMethodInvocationProcessor extends AbstractSleuthMethodInvocationProcessor { +class ReactorSleuthMethodInvocationProcessor + extends AbstractSleuthMethodInvocationProcessor { private NonReactorSleuthMethodInvocationProcessor nonReactorSleuthMethodInvocationProcessor; - @Override public Object process(MethodInvocation invocation, NewSpan newSpan, + @Override + public Object process(MethodInvocation invocation, NewSpan newSpan, ContinueSpan continueSpan) throws Throwable { Method method = invocation.getMethod(); - if(isReactorReturnType(method.getReturnType())){ + if (isReactorReturnType(method.getReturnType())) { return proceedUnderReactorSpan(invocation, newSpan, continueSpan); - } else { - return nonReactorSleuthMethodInvocationProcessor() - .process(invocation, newSpan, continueSpan); + } + else { + return nonReactorSleuthMethodInvocationProcessor().process(invocation, + newSpan, continueSpan); } } - private Object proceedUnderReactorSpan( - MethodInvocation invocation, NewSpan newSpan, ContinueSpan continueSpan) throws Throwable{ + private Object proceedUnderReactorSpan(MethodInvocation invocation, NewSpan newSpan, + ContinueSpan continueSpan) throws Throwable { Span spanPrevious = tracer().currentSpan(); - //in case of @ContinueSpan and no span in tracer we start new span and should close it on completion + // in case of @ContinueSpan and no span in tracer we start new span and should + // close it on completion boolean startNewSpan = newSpan != null || spanPrevious == null; Span span; if (startNewSpan) { span = tracer().nextSpan(); newSpanParser().parse(invocation, newSpan, span); - } else { + } + else { span = spanPrevious; } String log = log(continueSpan); boolean hasLog = StringUtils.hasText(log); - try(Tracer.SpanInScope ws = tracer().withSpanInScope(span)) { + try (Tracer.SpanInScope ws = tracer().withSpanInScope(span)) { Publisher publisher = (Publisher) invocation.proceed(); Mono startSpan = Mono.defer(() -> withSpanInScope(span, () -> { if (startNewSpan) { @@ -71,35 +78,43 @@ class ReactorSleuthMethodInvocationProcessor extends AbstractSleuthMethodInvocat before(invocation, span, log, hasLog); return Mono.just(span); })); - if(publisher instanceof Mono){ - return startSpan.flatMap(spanStarted -> ((Mono)publisher) - .doOnError(onFailureReactor(log, hasLog, spanStarted)) - .doFinally(afterReactor(startNewSpan, log, hasLog, spanStarted))) - //put span in context so it can be used by ScopePassingSpanSubscriber + if (publisher instanceof Mono) { + return startSpan + .flatMap(spanStarted -> ((Mono) publisher) + .doOnError(onFailureReactor(log, hasLog, spanStarted)) + .doFinally(afterReactor(startNewSpan, log, hasLog, + spanStarted))) + // put span in context so it can be used by + // ScopePassingSpanSubscriber .subscriberContext(context -> context.put(Span.class, span)); } - else if(publisher instanceof Flux){ - return startSpan.flatMapMany(spanStarted -> ((Flux)publisher) - .doOnError(onFailureReactor(log, hasLog, spanStarted)) - .doFinally(afterReactor(startNewSpan, log, hasLog, spanStarted))) - //put span in context so it can be used by ScopePassingSpanSubscriber + else if (publisher instanceof Flux) { + return startSpan + .flatMapMany(spanStarted -> ((Flux) publisher) + .doOnError(onFailureReactor(log, hasLog, spanStarted)) + .doFinally(afterReactor(startNewSpan, log, hasLog, + spanStarted))) + // put span in context so it can be used by + // ScopePassingSpanSubscriber .subscriberContext(context -> context.put(Span.class, span)); } else { - throw new IllegalArgumentException("Unexpected type of publisher: "+publisher.getClass()); + throw new IllegalArgumentException( + "Unexpected type of publisher: " + publisher.getClass()); } } } private T withSpanInScope(Span span, Supplier supplier) { - try(Tracer.SpanInScope ws1 = tracer().withSpanInScope(span)) { + try (Tracer.SpanInScope ws1 = tracer().withSpanInScope(span)) { return supplier.get(); } } - private Consumer afterReactor(boolean isNewSpan, String log, boolean hasLog, Span span) { + private Consumer afterReactor(boolean isNewSpan, String log, + boolean hasLog, Span span) { return signalType -> { - try(Tracer.SpanInScope ws = tracer().withSpanInScope(span)) { + try (Tracer.SpanInScope ws = tracer().withSpanInScope(span)) { after(span, isNewSpan, log, hasLog); } }; @@ -107,7 +122,7 @@ class ReactorSleuthMethodInvocationProcessor extends AbstractSleuthMethodInvocat private Consumer onFailureReactor(String log, boolean hasLog, Span span) { return throwable -> { - try(Tracer.SpanInScope ws = tracer().withSpanInScope(span)) { + try (Tracer.SpanInScope ws = tracer().withSpanInScope(span)) { onFailure(span, log, hasLog, throwable); } }; @@ -120,8 +135,10 @@ class ReactorSleuthMethodInvocationProcessor extends AbstractSleuthMethodInvocat private NonReactorSleuthMethodInvocationProcessor nonReactorSleuthMethodInvocationProcessor() { if (this.nonReactorSleuthMethodInvocationProcessor == null) { this.nonReactorSleuthMethodInvocationProcessor = new NonReactorSleuthMethodInvocationProcessor(); - this.nonReactorSleuthMethodInvocationProcessor.setBeanFactory(this.beanFactory); + this.nonReactorSleuthMethodInvocationProcessor + .setBeanFactory(this.beanFactory); } return this.nonReactorSleuthMethodInvocationProcessor; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAdvisorConfig.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAdvisorConfig.java index b5780d291..c326f73bc 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAdvisorConfig.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAdvisorConfig.java @@ -37,8 +37,8 @@ import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.ReflectionUtils; /** - * Custom pointcut advisor that picks all classes / interfaces that - * have the Sleuth related annotations. + * Custom pointcut advisor that picks all classes / interfaces that have the Sleuth + * related annotations. * * @author Marcin Grzejszczak * @since 1.2.0 @@ -88,22 +88,26 @@ class SleuthAdvisorConfig extends AbstractPointcutAdvisor implements BeanFactory } /** - * Checks if a class or a method is is annotated with Sleuth related annotations + * Checks if a class or a method is is annotated with Sleuth related annotations. */ - private final class AnnotationClassOrMethodOrArgsPointcut extends - DynamicMethodMatcherPointcut { + private final class AnnotationClassOrMethodOrArgsPointcut + extends DynamicMethodMatcherPointcut { @Override public boolean matches(Method method, Class targetClass, Object... args) { - //Skip check here as actual check takes place in SleuthInterceptor.invoke(MethodInvocation) + // Skip check here as actual check takes place in + // SleuthInterceptor.invoke(MethodInvocation) return true; } - @Override public ClassFilter getClassFilter() { + @Override + public ClassFilter getClassFilter() { return new ClassFilter() { - @Override public boolean matches(Class clazz) { - return new AnnotationClassOrMethodFilter(NewSpan.class).matches(clazz) || - new AnnotationClassOrMethodFilter(ContinueSpan.class).matches(clazz); + @Override + public boolean matches(Class clazz) { + return new AnnotationClassOrMethodFilter(NewSpan.class).matches(clazz) + || new AnnotationClassOrMethodFilter(ContinueSpan.class) + .matches(clazz); } }; } @@ -127,39 +131,45 @@ class SleuthAdvisorConfig extends AbstractPointcutAdvisor implements BeanFactory } /** - * Checks if a method is properly annotated with a given Sleuth annotation + * Checks if a method is properly annotated with a given Sleuth annotation. */ private static class AnnotationMethodsResolver { private final Class annotationType; - public AnnotationMethodsResolver(Class annotationType) { + AnnotationMethodsResolver(Class annotationType) { this.annotationType = annotationType; } - public boolean hasAnnotatedMethods(Class clazz) { + boolean hasAnnotatedMethods(Class clazz) { final AtomicBoolean found = new AtomicBoolean(false); - ReflectionUtils.doWithMethods(clazz, method -> { + ReflectionUtils.doWithMethods(clazz, (method -> { if (found.get()) { return; } Annotation annotation = AnnotationUtils.findAnnotation(method, AnnotationMethodsResolver.this.annotationType); - if (annotation != null) { found.set(true); } - }); + if (annotation != null) { + found.set(true); + } + })); return found.get(); } } + } /** - * Interceptor that creates or continues a span depending on the provided - * annotation. Also it adds logs and tags if necessary. + * Interceptor that creates or continues a span depending on the provided annotation. Also + * it adds logs and tags if necessary. + * + * @author Marcin Grzejszczak */ -class SleuthInterceptor implements IntroductionInterceptor, BeanFactoryAware { +class SleuthInterceptor implements IntroductionInterceptor, BeanFactoryAware { private BeanFactory beanFactory; + private SleuthMethodInvocationProcessor methodInvocationProcessor; @Override @@ -168,10 +178,12 @@ class SleuthInterceptor implements IntroductionInterceptor, BeanFactoryAware { if (method == null) { return invocation.proceed(); } - Method mostSpecificMethod = AopUtils - .getMostSpecificMethod(method, invocation.getThis().getClass()); - NewSpan newSpan = SleuthAnnotationUtils.findAnnotation(mostSpecificMethod, NewSpan.class); - ContinueSpan continueSpan = SleuthAnnotationUtils.findAnnotation(mostSpecificMethod, ContinueSpan.class); + Method mostSpecificMethod = AopUtils.getMostSpecificMethod(method, + invocation.getThis().getClass()); + NewSpan newSpan = SleuthAnnotationUtils.findAnnotation(mostSpecificMethod, + NewSpan.class); + ContinueSpan continueSpan = SleuthAnnotationUtils + .findAnnotation(mostSpecificMethod, ContinueSpan.class); if (newSpan == null && continueSpan == null) { return invocation.proceed(); } @@ -180,16 +192,20 @@ class SleuthInterceptor implements IntroductionInterceptor, BeanFactoryAware { private SleuthMethodInvocationProcessor methodInvocationProcessor() { if (this.methodInvocationProcessor == null) { - this.methodInvocationProcessor = this.beanFactory.getBean(SleuthMethodInvocationProcessor.class); + this.methodInvocationProcessor = this.beanFactory + .getBean(SleuthMethodInvocationProcessor.class); } return this.methodInvocationProcessor; } - @Override public boolean implementsInterface(Class intf) { + @Override + public boolean implementsInterface(Class intf) { return true; } - @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotatedParameter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotatedParameter.java index bbea6c381..4c253528d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotatedParameter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotatedParameter.java @@ -16,8 +16,8 @@ package org.springframework.cloud.sleuth.annotation; /** - * A container class that holds information about the parameter - * of the annotated method argument. + * A container class that holds information about the parameter of the annotated method + * argument. * * @author Christian Schwerdtfeger * @since 1.2.0 @@ -25,11 +25,12 @@ package org.springframework.cloud.sleuth.annotation; class SleuthAnnotatedParameter { final int parameterIndex; + final SpanTag annotation; + final Object argument; - SleuthAnnotatedParameter(int parameterIndex, SpanTag annotation, - Object argument) { + SleuthAnnotatedParameter(int parameterIndex, SpanTag annotation, Object argument) { this.parameterIndex = parameterIndex; this.annotation = annotation; this.argument = argument; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationAutoConfiguration.java index d822bed10..714c93861 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationAutoConfiguration.java @@ -30,9 +30,9 @@ import org.springframework.context.annotation.Role; /** * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration - * Auto-configuration} that allows creating spans by means of a - * {@link NewSpan} annotation. You can annotate classes or just methods. - * You can also apply this annotation to an interface. + * Auto-configuration} that allows creating spans by means of a {@link NewSpan} + * annotation. You can annotate classes or just methods. You can also apply this + * annotation to an interface. * * @author Christian Schwerdtfeger * @author Marcin Grzejszczak @@ -44,24 +44,28 @@ import org.springframework.context.annotation.Role; @ConditionalOnProperty(name = "spring.sleuth.annotation.enabled", matchIfMissing = true) @AutoConfigureAfter(TraceAutoConfiguration.class) public class SleuthAnnotationAutoConfiguration { - + @Bean - @ConditionalOnMissingBean NewSpanParser newSpanParser() { - return new DefaultNewSpanParser(); + @ConditionalOnMissingBean + NewSpanParser newSpanParser() { + return new DefaultSpanCreator(); } @Bean - @ConditionalOnMissingBean TagValueExpressionResolver spelTagValueExpressionResolver() { + @ConditionalOnMissingBean + TagValueExpressionResolver spelTagValueExpressionResolver() { return new SpelTagValueExpressionResolver(); } @Bean - @ConditionalOnMissingBean TagValueResolver noOpTagValueResolver() { + @ConditionalOnMissingBean + TagValueResolver noOpTagValueResolver() { return new NoOpTagValueResolver(); } @Bean - @Role(BeanDefinition.ROLE_INFRASTRUCTURE) SleuthAdvisorConfig sleuthAdvisorConfig() { + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + SleuthAdvisorConfig sleuthAdvisorConfig() { return new SleuthAdvisorConfig(); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationProperties.java index 87cfa0b70..ed8f7ffa4 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationProperties.java @@ -19,7 +19,7 @@ package org.springframework.cloud.sleuth.annotation; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Sleuth annotation settings + * Sleuth annotation settings. * * @author Marcin Grzejszczak * @since 1.2.0 @@ -36,4 +36,5 @@ public class SleuthAnnotationProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationUtils.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationUtils.java index b08b24c7d..07b3aad53 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationUtils.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthAnnotationUtils.java @@ -26,33 +26,39 @@ import org.apache.commons.logging.LogFactory; import org.springframework.core.annotation.AnnotationUtils; /** - * Utility class that can verify whether the method is annotated with - * the Sleuth annotations. + * Utility class that can verify whether the method is annotated with the Sleuth + * annotations. * * @author Christian Schwerdtfeger * @since 1.2.0 */ class SleuthAnnotationUtils { + private SleuthAnnotationUtils() { + + } + private static final Log log = LogFactory.getLog(SleuthAnnotationUtils.class); static boolean isMethodAnnotated(Method method) { - return findAnnotation(method, NewSpan.class) != null || - findAnnotation(method, ContinueSpan.class) != null; + return findAnnotation(method, NewSpan.class) != null + || findAnnotation(method, ContinueSpan.class) != null; } static boolean hasAnnotatedParams(Method method, Object[] args) { return !findAnnotatedParameters(method, args).isEmpty(); } - static List findAnnotatedParameters(Method method, Object[] args) { + static List findAnnotatedParameters(Method method, + Object[] args) { Annotation[][] parameters = method.getParameterAnnotations(); List result = new ArrayList<>(); int i = 0; for (Annotation[] parameter : parameters) { for (Annotation parameter2 : parameter) { if (parameter2 instanceof SpanTag) { - result.add(new SleuthAnnotatedParameter(i, (SpanTag) parameter2, args[i])); + result.add(new SleuthAnnotatedParameter(i, (SpanTag) parameter2, + args[i])); } } i++; @@ -61,21 +67,28 @@ class SleuthAnnotationUtils { } /** - * Searches for an annotation either on a method or inside the method parameters + * Searches for an annotation either on a method or inside the method parameters. + * + * @param - annotation + * @param clazz - class with annotation + * @param method - annotated method + * @return annotation */ static T findAnnotation(Method method, Class clazz) { T annotation = AnnotationUtils.findAnnotation(method, clazz); if (annotation == null) { try { - annotation = AnnotationUtils.findAnnotation( - method.getDeclaringClass().getMethod(method.getName(), - method.getParameterTypes()), clazz); - } catch (NoSuchMethodException | SecurityException e) { + annotation = AnnotationUtils.findAnnotation(method.getDeclaringClass() + .getMethod(method.getName(), method.getParameterTypes()), clazz); + } + catch (NoSuchMethodException | SecurityException ex) { if (log.isDebugEnabled()) { - log.debug("Exception occurred while tyring to find the annotation", e); + log.debug("Exception occurred while tyring to find the annotation", + ex); } } } return annotation; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthMethodInvocationProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthMethodInvocationProcessor.java index a4ce3ffcb..c8d54a15f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthMethodInvocationProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SleuthMethodInvocationProcessor.java @@ -19,10 +19,14 @@ package org.springframework.cloud.sleuth.annotation; import org.aopalliance.intercept.MethodInvocation; /** + * Contract for processing Sleuth annotations. + * * @author Marcin Grzejszczak * @since 2.1.0 */ interface SleuthMethodInvocationProcessor { - Object process(MethodInvocation invocation, NewSpan newSpan, ContinueSpan continueSpan) throws Throwable; + Object process(MethodInvocation invocation, NewSpan newSpan, + ContinueSpan continueSpan) throws Throwable; + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpanTag.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpanTag.java index 8259d2517..6e536b582 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpanTag.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpanTag.java @@ -25,43 +25,46 @@ import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; /** - * There are 3 different ways to add tags to a span. All of them are controlled by the annotation values. - * Precedence is: + * There are 3 different ways to add tags to a span. All of them are controlled by the + * annotation values. Precedence is: * - *

      - *
    • try with the {@link TagValueResolver} bean
    • - *
    • if the value of the bean wasn't set, try to evaluate a SPEL expression
    • - *
    • if there’s no SPEL expression just return a {@code toString()} value of the parameter
    • - *
    + *
      + *
    • try with the {@link TagValueResolver} bean
    • + *
    • if the value of the bean wasn't set, try to evaluate a SPEL expression
    • + *
    • if there’s no SPEL expression just return a {@code toString()} value of the + * parameter
    • + *
    * * @author Christian Schwerdtfeger * @since 1.2.0 */ @Retention(RetentionPolicy.RUNTIME) @Inherited -@Target(value = { ElementType.PARAMETER }) +@Target(value = { + ElementType.PARAMETER +}) public @interface SpanTag { /** - * The name of the key of the tag which should be created. + * @return - The name of the key of the tag which should be created. */ @AliasFor("key") String value() default ""; /** - * The name of the key of the tag which should be created. + * @return - The name of the key of the tag which should be created. */ @AliasFor("value") String key() default ""; /** - * Execute this SPEL expression to calculate the tag value. Will be analyzed if no value of the - * {@link SpanTag#resolver()} was set. + * @return - Execute this SPEL expression to calculate the tag value. Will be analyzed if no + * value of the {@link SpanTag#resolver()} was set. */ String expression() default ""; /** - * Use this bean to resolve the tag value. Has the highest precedence. + * @return - Use this bean to resolve the tag value. Has the highest precedence. */ Class resolver() default NoOpTagValueResolver.class; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpanTagAnnotationHandler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpanTagAnnotationHandler.java index 31e73c475..8d6b51253 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpanTagAnnotationHandler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpanTagAnnotationHandler.java @@ -29,13 +29,13 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.util.StringUtils; /** - * This class is able to find all methods annotated with the - * Sleuth annotations. All methods mean that if you have both an interface - * and an implementation annotated with Sleuth annotations then this class is capable - * of finding both of them and merging into one set of tracing information. + * This class is able to find all methods annotated with the Sleuth annotations. All + * methods mean that if you have both an interface and an implementation annotated with + * Sleuth annotations then this class is capable of finding both of them and merging into + * one set of tracing information. * - * This information is then used to add proper tags to the span from the - * method arguments that are annotated with {@link SpanTag}. + * This information is then used to add proper tags to the span from the method arguments + * that are annotated with {@link SpanTag}. * * @author Christian Schwerdtfeger * @since 1.2.0 @@ -45,8 +45,9 @@ class SpanTagAnnotationHandler { private static final Log log = LogFactory.getLog(SpanTagAnnotationHandler.class); private final BeanFactory beanFactory; + private SpanCustomizer spanCustomizer; - + SpanTagAnnotationHandler(BeanFactory beanFactory) { this.beanFactory = beanFactory; } @@ -56,14 +57,15 @@ class SpanTagAnnotationHandler { Method method = pjp.getMethod(); Method mostSpecificMethod = AopUtils.getMostSpecificMethod(method, pjp.getThis().getClass()); - List annotatedParameters = - SleuthAnnotationUtils.findAnnotatedParameters(mostSpecificMethod, pjp.getArguments()); + List annotatedParameters = SleuthAnnotationUtils + .findAnnotatedParameters(mostSpecificMethod, pjp.getArguments()); getAnnotationsFromInterfaces(pjp, mostSpecificMethod, annotatedParameters); mergeAnnotatedMethodsIfNecessary(pjp, method, mostSpecificMethod, annotatedParameters); addAnnotatedArguments(annotatedParameters); - } catch (SecurityException e) { - log.error("Exception occurred while trying to add annotated parameters", e); + } + catch (SecurityException ex) { + log.error("Exception occurred while trying to add annotated parameters", ex); } } @@ -75,9 +77,11 @@ class SpanTagAnnotationHandler { for (Class implementedInterface : implementedInterfaces) { for (Method methodFromInterface : implementedInterface.getMethods()) { if (methodsAreTheSame(mostSpecificMethod, methodFromInterface)) { - List annotatedParametersForActualMethod = - SleuthAnnotationUtils.findAnnotatedParameters(methodFromInterface, pjp.getArguments()); - mergeAnnotatedParameters(annotatedParameters, annotatedParametersForActualMethod); + List annotatedParametersForActualMethod = SleuthAnnotationUtils + .findAnnotatedParameters(methodFromInterface, + pjp.getArguments()); + mergeAnnotatedParameters(annotatedParameters, + annotatedParametersForActualMethod); } } } @@ -85,22 +89,25 @@ class SpanTagAnnotationHandler { } private boolean methodsAreTheSame(Method mostSpecificMethod, Method method1) { - return method1.getName().equals(mostSpecificMethod.getName()) && - Arrays.equals(method1.getParameterTypes(), mostSpecificMethod.getParameterTypes()); + return method1.getName().equals(mostSpecificMethod.getName()) && Arrays.equals( + method1.getParameterTypes(), mostSpecificMethod.getParameterTypes()); } private void mergeAnnotatedMethodsIfNecessary(MethodInvocation pjp, Method method, - Method mostSpecificMethod, List annotatedParameters) { + Method mostSpecificMethod, + List annotatedParameters) { // that can happen if we have an abstraction and a concrete class that is // annotated with @NewSpan annotation if (!method.equals(mostSpecificMethod)) { - List annotatedParametersForActualMethod = SleuthAnnotationUtils.findAnnotatedParameters( - method, pjp.getArguments()); - mergeAnnotatedParameters(annotatedParameters, annotatedParametersForActualMethod); + List annotatedParametersForActualMethod = SleuthAnnotationUtils + .findAnnotatedParameters(method, pjp.getArguments()); + mergeAnnotatedParameters(annotatedParameters, + annotatedParametersForActualMethod); } } - private void mergeAnnotatedParameters(List annotatedParametersIndices, + private void mergeAnnotatedParameters( + List annotatedParametersIndices, List annotatedParametersIndicesForActualMethod) { for (SleuthAnnotatedParameter container : annotatedParametersIndicesForActualMethod) { final int index = container.parameterIndex; @@ -132,11 +139,9 @@ class SpanTagAnnotationHandler { return this.spanCustomizer; } - - private String resolveTagKey( - SleuthAnnotatedParameter container) { - return StringUtils.hasText(container.annotation.value()) ? - container.annotation.value() : container.annotation.key(); + private String resolveTagKey(SleuthAnnotatedParameter container) { + return StringUtils.hasText(container.annotation.value()) + ? container.annotation.value() : container.annotation.key(); } String resolveTagValue(SpanTag annotation, Object argument) { @@ -144,12 +149,15 @@ class SpanTagAnnotationHandler { return ""; } if (annotation.resolver() != NoOpTagValueResolver.class) { - TagValueResolver tagValueResolver = this.beanFactory.getBean(annotation.resolver()); + TagValueResolver tagValueResolver = this.beanFactory + .getBean(annotation.resolver()); return tagValueResolver.resolve(argument); - } else if (StringUtils.hasText(annotation.expression())) { + } + else if (StringUtils.hasText(annotation.expression())) { return this.beanFactory.getBean(TagValueExpressionResolver.class) .resolve(annotation.expression(), argument); } return argument.toString(); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpelTagValueExpressionResolver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpelTagValueExpressionResolver.java index b2b06824b..df6fcf42c 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpelTagValueExpressionResolver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/SpelTagValueExpressionResolver.java @@ -24,27 +24,32 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.SimpleEvaluationContext; /** - * Uses SPEL to evaluate the expression. If an exception is thrown will return - * the {@code toString()} of the parameter. + * Uses SPEL to evaluate the expression. If an exception is thrown will return the + * {@code toString()} of the parameter. * * @author Marcin Grzejszczak * @since 1.2.0 */ class SpelTagValueExpressionResolver implements TagValueExpressionResolver { - private static final Log log = LogFactory.getLog(SpelTagValueExpressionResolver.class); + + private static final Log log = LogFactory + .getLog(SpelTagValueExpressionResolver.class); @Override public String resolve(String expression, Object parameter) { try { SimpleEvaluationContext context = SimpleEvaluationContext - .forReadOnlyDataBinding() - .build(); + .forReadOnlyDataBinding().build(); ExpressionParser expressionParser = new SpelExpressionParser(); - Expression expressionToEvaluate = expressionParser.parseExpression(expression); + Expression expressionToEvaluate = expressionParser + .parseExpression(expression); return expressionToEvaluate.getValue(context, parameter, String.class); - } catch (Exception e) { - log.error("Exception occurred while tying to evaluate the SPEL expression [" + expression + "]", e); + } + catch (Exception ex) { + log.error("Exception occurred while tying to evaluate the SPEL expression [" + + expression + "]", ex); } return parameter.toString(); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/TagValueExpressionResolver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/TagValueExpressionResolver.java index 9e6176ec8..ae6be9056 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/TagValueExpressionResolver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/TagValueExpressionResolver.java @@ -25,12 +25,11 @@ package org.springframework.cloud.sleuth.annotation; public interface TagValueExpressionResolver { /** - * Returns the tag value for the given parameter and the provided expression - * + * Returns the tag value for the given parameter and the provided expression. * @param expression - the expression coming from {@link SpanTag#expression()} * @param parameter - parameter annotated with {@link SpanTag} * @return the value of the tag */ String resolve(String expression, Object parameter); - + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/TagValueResolver.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/TagValueResolver.java index ac558423b..32d1690fe 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/TagValueResolver.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/annotation/TagValueResolver.java @@ -25,11 +25,10 @@ package org.springframework.cloud.sleuth.annotation; public interface TagValueResolver { /** - * Returns the tag value for the given parameter - * + * Returns the tag value for the given parameter. * @param parameter - parameter annotated with {@link SpanTag} * @return the value of the tag */ String resolve(Object parameter); - + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/SleuthProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/SleuthProperties.java index 878314cc6..0b40aee78 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/SleuthProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/SleuthProperties.java @@ -22,8 +22,9 @@ import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Sleuth settings + * Sleuth settings. * + * @author Marcin Grzejszczak * @since 1.0.11 */ @ConfigurationProperties("spring.sleuth") @@ -34,24 +35,28 @@ public class SleuthProperties { /** When true, generate 128-bit trace IDs instead of 64-bit ones. */ private boolean traceId128 = false; - /** True means the tracing system supports sharing a span ID between a client and server. */ + /** + * True means the tracing system supports sharing a span ID between a client and + * server. + */ private boolean supportsJoin = true; /** - * List of baggage key names that should be propagated out of process. - * These keys will be prefixed with `baggage` before the actual key. - * This property is set in order to be backward compatible with previous - * Sleuth versions. + * List of baggage key names that should be propagated out of process. These keys will + * be prefixed with `baggage` before the actual key. This property is set in order to + * be backward compatible with previous Sleuth versions. * - * @see brave.propagation.ExtraFieldPropagation.FactoryBuilder#addPrefixedFields(String, java.util.Collection) + * @see brave.propagation.ExtraFieldPropagation.FactoryBuilder#addPrefixedFields(String, + * java.util.Collection) */ private List baggageKeys = new ArrayList<>(); /** - * List of fields that are referenced the same in-process as it is on the wire. For example, the - * name "x-vcap-request-id" would be set as-is including the prefix. + * List of fields that are referenced the same in-process as it is on the wire. For + * example, the name "x-vcap-request-id" would be set as-is including the prefix. * - *

    Note: {@code fieldName} will be implicitly lower-cased. + *

    + * Note: {@code fieldName} will be implicitly lower-cased. * * @see brave.propagation.ExtraFieldPropagation.FactoryBuilder#addField(String) */ @@ -96,4 +101,5 @@ public class SleuthProperties { public void setPropagationKeys(List propagationKeys) { this.propagationKeys = propagationKeys; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java index de43d1788..8b5c92555 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java @@ -44,41 +44,43 @@ import zipkin2.Span; import zipkin2.reporter.Reporter; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * to enable tracing via Spring Cloud Sleuth. + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} to enable tracing via Spring Cloud Sleuth. * * @author Spencer Gibb * @author Marcin Grzejszczak * @since 2.0.0 */ @Configuration -@ConditionalOnProperty(value="spring.sleuth.enabled", matchIfMissing=true) +@ConditionalOnProperty(value = "spring.sleuth.enabled", matchIfMissing = true) @EnableConfigurationProperties(SleuthProperties.class) public class TraceAutoConfiguration { + /** + * Tracer bean name. Name of the bean matters for some instrumentations. + */ public static final String TRACER_BEAN_NAME = "tracer"; - @Autowired(required = false) List spanAdjusters = new ArrayList<>(); - @Autowired(required = false) List finishedSpanHandlers = new ArrayList<>(); - @Autowired(required = false) List scopeDecorators = new ArrayList<>(); + @Autowired(required = false) + List spanAdjusters = new ArrayList<>(); + + @Autowired(required = false) + List finishedSpanHandlers = new ArrayList<>(); + + @Autowired(required = false) + List scopeDecorators = new ArrayList<>(); @Bean @ConditionalOnMissingBean // NOTE: stable bean name as might be used outside sleuth - Tracing tracing(@Value("${spring.zipkin.service.name:${spring.application.name:default}}") String serviceName, - Propagation.Factory factory, - CurrentTraceContext currentTraceContext, - Reporter reporter, - Sampler sampler, - ErrorParser errorParser, - SleuthProperties sleuthProperties - ) { - Tracing.Builder builder = Tracing.newBuilder() - .sampler(sampler) - .errorParser(errorParser) - .localServiceName(serviceName) - .propagationFactory(factory) - .currentTraceContext(currentTraceContext) + Tracing tracing( + @Value("${spring.zipkin.service.name:${spring.application.name:default}}") String serviceName, + Propagation.Factory factory, CurrentTraceContext currentTraceContext, + Reporter reporter, Sampler sampler, ErrorParser errorParser, + SleuthProperties sleuthProperties) { + Tracing.Builder builder = Tracing.newBuilder().sampler(sampler) + .errorParser(errorParser).localServiceName(serviceName) + .propagationFactory(factory).currentTraceContext(currentTraceContext) .spanReporter(adjustedReporter(reporter)) .traceId128Bit(sleuthProperties.isTraceId128()) .supportsJoin(sleuthProperties.isSupportsJoin()); @@ -89,7 +91,7 @@ public class TraceAutoConfiguration { } private Reporter adjustedReporter(Reporter delegate) { - return span -> { + return (span) -> { Span spanToAdjust = span; for (SpanAdjuster spanAdjuster : this.spanAdjusters) { spanToAdjust = spanAdjuster.adjust(spanToAdjust); @@ -111,14 +113,16 @@ public class TraceAutoConfiguration { } @Bean - @ConditionalOnMissingBean SpanNamer sleuthSpanNamer() { + @ConditionalOnMissingBean + SpanNamer sleuthSpanNamer() { return new DefaultSpanNamer(); } @Bean @ConditionalOnMissingBean Propagation.Factory sleuthPropagation(SleuthProperties sleuthProperties) { - if (sleuthProperties.getBaggageKeys().isEmpty() && sleuthProperties.getPropagationKeys().isEmpty()) { + if (sleuthProperties.getBaggageKeys().isEmpty() + && sleuthProperties.getPropagationKeys().isEmpty()) { return B3Propagation.FACTORY; } ExtraFieldPropagation.FactoryBuilder factoryBuilder = ExtraFieldPropagation @@ -170,4 +174,5 @@ public class TraceAutoConfiguration { CurrentSpanCustomizer spanCustomizer(Tracing tracing) { return CurrentSpanCustomizer.create(tracing); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceEnvironmentPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceEnvironmentPostProcessor.java index e155411ac..9fba6a093 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceEnvironmentPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceEnvironmentPostProcessor.java @@ -29,7 +29,7 @@ import org.springframework.core.env.PropertySource; /** * Adds default properties for the application: *

      - *
    • logging pattern level that prints trace information (e.g. trace ids)
    • + *
    • logging pattern level that prints trace information (e.g. trace ids)
    • *
    * * @author Dave Syer @@ -46,7 +46,8 @@ public class TraceEnvironmentPostProcessor implements EnvironmentPostProcessor { Map map = new HashMap(); // This doesn't work with all logging systems but it's a useful default so you see // traces in logs without having to configure it. - if (Boolean.parseBoolean(environment.getProperty("spring.sleuth.enabled", "true"))) { + if (Boolean + .parseBoolean(environment.getProperty("spring.sleuth.enabled", "true"))) { map.put("logging.pattern.level", "%5p [${spring.zipkin.service.name:${spring.application.name:-}},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]"); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncAutoConfiguration.java index 5b9facb0e..78bc480b8 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncAutoConfiguration.java @@ -21,8 +21,9 @@ 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} + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} that wraps an existing custom {@link AsyncConfigurer} in a + * {@link LazyTraceAsyncCustomizer}. * * @author Jesus Alonso * @since 2.1.0 @@ -30,4 +31,5 @@ import org.springframework.scheduling.annotation.AsyncConfigurer; @Configuration @EnableConfigurationProperties(SleuthAsyncProperties.class) public class AsyncAutoConfiguration { + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfiguration.java index 163959645..c4f190d79 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfiguration.java @@ -29,8 +29,9 @@ 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} + * {@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 @@ -54,11 +55,12 @@ public class AsyncCustomAutoConfiguration implements BeanPostProcessor { @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof AsyncConfigurer && !(bean instanceof LazyTraceAsyncCustomizer)) { + if (bean instanceof AsyncConfigurer + && !(bean instanceof LazyTraceAsyncCustomizer)) { AsyncConfigurer configurer = (AsyncConfigurer) bean; return new LazyTraceAsyncCustomizer(this.beanFactory, configurer); } return bean; } -} \ No newline at end of file +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfiguration.java index 053dc5ff4..24b4d5bd8 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfiguration.java @@ -35,13 +35,12 @@ import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.AsyncConfigurerSupport; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * enabling async related processing. + * {@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 */ @@ -50,18 +49,10 @@ import org.springframework.scheduling.annotation.AsyncConfigurerSupport; @ConditionalOnBean(Tracing.class) public class AsyncDefaultAutoConfiguration { - @Configuration - @ConditionalOnMissingBean(AsyncConfigurer.class) - @ConditionalOnProperty(value = "spring.sleuth.async.configurer.enabled", matchIfMissing = true) - @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - static class DefaultAsyncConfigurerSupport extends AsyncConfigurerSupport { - - @Autowired private BeanFactory beanFactory; - - @Override - public Executor getAsyncExecutor() { - return new LazyTraceExecutor(this.beanFactory, new SimpleAsyncTaskExecutor()); - } + @Bean + public static ExecutorBeanPostProcessor executorBeanPostProcessor( + BeanFactory beanFactory) { + return new ExecutorBeanPostProcessor(beanFactory); } @Bean @@ -69,9 +60,23 @@ public class AsyncDefaultAutoConfiguration { return new TraceAsyncAspect(tracer, spanNamer); } - @Bean - public static ExecutorBeanPostProcessor executorBeanPostProcessor(BeanFactory beanFactory) { - return new ExecutorBeanPostProcessor(beanFactory); + /** + * Wrapper for the async executor. + */ + @Configuration + @ConditionalOnMissingBean(AsyncConfigurer.class) + @ConditionalOnProperty(value = "spring.sleuth.async.configurer.enabled", matchIfMissing = true) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + static class DefaultAsyncConfigurerSupport extends AsyncConfigurerSupport { + + @Autowired + private BeanFactory beanFactory; + + @Override + public Executor getAsyncExecutor() { + return new LazyTraceExecutor(this.beanFactory, new SimpleAsyncTaskExecutor()); + } + } -} \ No newline at end of file +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java index 15515673b..1d3858463 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java @@ -34,9 +34,8 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.util.ReflectionUtils; /** - * Bean post processor that wraps a call to an {@link Executor} either in a - * JDK or CGLIB proxy. Depending on whether the implementation has a final - * method or is final. + * Bean post processor that wraps a call to an {@link Executor} either in a JDK or CGLIB + * proxy. Depending on whether the implementation has a final method or is final. * * @author Marcin Grzejszczak * @author Jesus Alonso @@ -45,10 +44,10 @@ import org.springframework.util.ReflectionUtils; */ class ExecutorBeanPostProcessor implements BeanPostProcessor { - private static final Log log = LogFactory.getLog( - ExecutorBeanPostProcessor.class); + private static final Log log = LogFactory.getLog(ExecutorBeanPostProcessor.class); private final BeanFactory beanFactory; + private SleuthAsyncProperties sleuthAsyncProperties; ExecutorBeanPostProcessor(BeanFactory beanFactory) { @@ -65,29 +64,35 @@ class ExecutorBeanPostProcessor implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Executor && !(bean instanceof ThreadPoolTaskExecutor)) { - Method execute = ReflectionUtils.findMethod(bean.getClass(), "execute", Runnable.class); + Method execute = ReflectionUtils.findMethod(bean.getClass(), "execute", + Runnable.class); boolean methodFinal = Modifier.isFinal(execute.getModifiers()); boolean classFinal = Modifier.isFinal(bean.getClass().getModifiers()); boolean cglibProxy = !methodFinal && !classFinal; Executor executor = (Executor) bean; try { return createProxy(bean, cglibProxy, executor); - } catch (AopConfigException e) { + } + catch (AopConfigException ex) { if (cglibProxy) { if (log.isDebugEnabled()) { - log.debug("Exception occurred while trying to create a proxy, falling back to JDK proxy", e); + log.debug( + "Exception occurred while trying to create a proxy, falling back to JDK proxy", + ex); } return createProxy(bean, false, executor); } - throw e; + throw ex; } - } else if (bean instanceof ThreadPoolTaskExecutor) { + } + else if (bean instanceof ThreadPoolTaskExecutor) { if (isProxyNeeded(beanName)) { boolean classFinal = Modifier.isFinal(bean.getClass().getModifiers()); boolean cglibProxy = !classFinal; ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean; return createThreadPoolTaskExecutorProxy(bean, cglibProxy, executor); - } else { + } + else { log.info("Not instrumenting bean " + beanName); } } @@ -103,8 +108,10 @@ class ExecutorBeanPostProcessor implements BeanPostProcessor { ThreadPoolTaskExecutor executor) { ProxyFactoryBean factory = new ProxyFactoryBean(); factory.setProxyTargetClass(cglibProxy); - factory.addAdvice(new ExecutorMethodInterceptor(executor, this.beanFactory) { - @Override Executor executor(BeanFactory beanFactory, ThreadPoolTaskExecutor executor) { + factory.addAdvice(new ExecutorMethodInterceptor(executor, + this.beanFactory) { + @Override + Executor executor(BeanFactory beanFactory, ThreadPoolTaskExecutor executor) { return new LazyTraceThreadPoolTaskExecutor(beanFactory, executor); } }); @@ -120,18 +127,27 @@ class ExecutorBeanPostProcessor implements BeanPostProcessor { factory.setTarget(bean); return factory.getObject(); } - + private SleuthAsyncProperties asyncConfigurationProperties() { if (this.sleuthAsyncProperties == null) { - this.sleuthAsyncProperties = this.beanFactory.getBean(SleuthAsyncProperties.class); + this.sleuthAsyncProperties = this.beanFactory + .getBean(SleuthAsyncProperties.class); } return this.sleuthAsyncProperties; } + } +/** + * Interceptor for executor methods. + * + * @param - executor type + * @author Marcin Grzejszczak + */ class ExecutorMethodInterceptor implements MethodInterceptor { private final T delegate; + private final BeanFactory beanFactory; ExecutorMethodInterceptor(T delegate, BeanFactory beanFactory) { @@ -139,14 +155,15 @@ class ExecutorMethodInterceptor implements MethodInterceptor this.beanFactory = beanFactory; } - @Override public Object invoke(MethodInvocation invocation) - throws Throwable { + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { Executor executor = executor(this.beanFactory, this.delegate); Method methodOnTracedBean = getMethod(invocation, executor); if (methodOnTracedBean != null) { try { return methodOnTracedBean.invoke(executor, invocation.getArguments()); - } catch (InvocationTargetException ex) { + } + catch (InvocationTargetException ex) { // gh-1092: throw the target exception (if present) Throwable cause = ex.getCause(); throw (cause != null) ? cause : ex; @@ -157,11 +174,12 @@ class ExecutorMethodInterceptor implements MethodInterceptor private Method getMethod(MethodInvocation invocation, Object object) { Method method = invocation.getMethod(); - return ReflectionUtils - .findMethod(object.getClass(), method.getName(), method.getParameterTypes()); + return ReflectionUtils.findMethod(object.getClass(), method.getName(), + method.getParameterTypes()); } Executor executor(BeanFactory beanFactory, T executor) { return new LazyTraceExecutor(beanFactory, executor); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizer.java index 7d0ad3d9a..06f070bdb 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizer.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizer.java @@ -24,8 +24,8 @@ import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.AsyncConfigurerSupport; /** - * {@link AsyncConfigurerSupport} that creates a tracing data passing version - * of the {@link Executor} + * {@link AsyncConfigurerSupport} that creates a tracing data passing version of the + * {@link Executor}. * * @author Dave Syer * @since 1.0.0 @@ -33,6 +33,7 @@ import org.springframework.scheduling.annotation.AsyncConfigurerSupport; public class LazyTraceAsyncCustomizer extends AsyncConfigurerSupport { private final BeanFactory beanFactory; + private final AsyncConfigurer delegate; public LazyTraceAsyncCustomizer(BeanFactory beanFactory, AsyncConfigurer delegate) { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceExecutor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceExecutor.java index 926d44597..f18de2c42 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceExecutor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceExecutor.java @@ -27,7 +27,7 @@ import org.springframework.cloud.sleuth.DefaultSpanNamer; import org.springframework.cloud.sleuth.SpanNamer; /** - * {@link Executor} that wraps {@link Runnable} in a trace representation + * {@link Executor} that wraps {@link Runnable} in a trace representation. * * @author Dave Syer * @since 1.0.0 @@ -35,10 +35,9 @@ import org.springframework.cloud.sleuth.SpanNamer; public class LazyTraceExecutor implements Executor { private static final Log log = LogFactory.getLog(LazyTraceExecutor.class); - - private Tracing tracing; private final BeanFactory beanFactory; private final Executor delegate; + private Tracing tracing; private SpanNamer spanNamer; public LazyTraceExecutor(BeanFactory beanFactory, Executor delegate) { @@ -52,7 +51,7 @@ public class LazyTraceExecutor implements Executor { try { this.tracing = this.beanFactory.getBean(Tracing.class); } - catch (NoSuchBeanDefinitionException e) { + catch (NoSuchBeanDefinitionException ex) { this.delegate.execute(command); return; } @@ -66,11 +65,13 @@ public class LazyTraceExecutor implements Executor { try { this.spanNamer = this.beanFactory.getBean(SpanNamer.class); } - catch (NoSuchBeanDefinitionException e) { - log.warn("SpanNamer bean not found - will provide a manually created instance"); + catch (NoSuchBeanDefinitionException ex) { + log.warn( + "SpanNamer bean not found - will provide a manually created instance"); return new DefaultSpanNamer(); } } return this.spanNamer; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceThreadPoolTaskExecutor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceThreadPoolTaskExecutor.java index b6a5320f6..6a426d182 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceThreadPoolTaskExecutor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceThreadPoolTaskExecutor.java @@ -34,7 +34,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.util.concurrent.ListenableFuture; /** - * Trace representation of {@link ThreadPoolTaskExecutor} + * Trace representation of {@link ThreadPoolTaskExecutor}. * * @author Marcin Grzejszczak * @since 1.0.10 @@ -42,11 +42,15 @@ import org.springframework.util.concurrent.ListenableFuture; @SuppressWarnings("serial") public class LazyTraceThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { - private static final Log log = LogFactory.getLog(LazyTraceThreadPoolTaskExecutor.class); + private static final Log log = LogFactory + .getLog(LazyTraceThreadPoolTaskExecutor.class); private final BeanFactory beanFactory; + private final ThreadPoolTaskExecutor delegate; + private Tracing tracing; + private SpanNamer spanNamer; public LazyTraceThreadPoolTaskExecutor(BeanFactory beanFactory, @@ -62,7 +66,8 @@ public class LazyTraceThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { @Override public void execute(Runnable task, long startTimeout) { - this.delegate.execute(new TraceRunnable(tracing(), spanNamer(), task), startTimeout); + this.delegate.execute(new TraceRunnable(tracing(), spanNamer(), task), + startTimeout); } @Override @@ -77,41 +82,46 @@ public class LazyTraceThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { @Override public ListenableFuture submitListenable(Runnable task) { - return this.delegate.submitListenable(new TraceRunnable(tracing(), spanNamer(), task)); + return this.delegate + .submitListenable(new TraceRunnable(tracing(), spanNamer(), task)); } @Override public ListenableFuture submitListenable(Callable task) { - return this.delegate.submitListenable(new TraceCallable<>(tracing(), spanNamer(), task)); + return this.delegate + .submitListenable(new TraceCallable<>(tracing(), spanNamer(), task)); } - @Override public boolean prefersShortLivedTasks() { + @Override + public boolean prefersShortLivedTasks() { return this.delegate.prefersShortLivedTasks(); } - @Override public void setThreadFactory(ThreadFactory threadFactory) { + @Override + public void setThreadFactory(ThreadFactory threadFactory) { this.delegate.setThreadFactory(threadFactory); } - @Override public void setThreadNamePrefix(String threadNamePrefix) { - this.delegate.setThreadNamePrefix(threadNamePrefix); - } - - @Override public void setRejectedExecutionHandler( + @Override + public void setRejectedExecutionHandler( RejectedExecutionHandler rejectedExecutionHandler) { this.delegate.setRejectedExecutionHandler(rejectedExecutionHandler); } - @Override public void setWaitForTasksToCompleteOnShutdown( + @Override + public void setWaitForTasksToCompleteOnShutdown( boolean waitForJobsToCompleteOnShutdown) { - this.delegate.setWaitForTasksToCompleteOnShutdown(waitForJobsToCompleteOnShutdown); + this.delegate + .setWaitForTasksToCompleteOnShutdown(waitForJobsToCompleteOnShutdown); } - @Override public void setAwaitTerminationSeconds(int awaitTerminationSeconds) { + @Override + public void setAwaitTerminationSeconds(int awaitTerminationSeconds) { this.delegate.setAwaitTerminationSeconds(awaitTerminationSeconds); } - @Override public void setBeanName(String name) { + @Override + public void setBeanName(String name) { this.delegate.setBeanName(name); } @@ -120,11 +130,13 @@ public class LazyTraceThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { return this.delegate.getThreadPoolExecutor(); } - @Override public int getPoolSize() { + @Override + public int getPoolSize() { return this.delegate.getPoolSize(); } - @Override public int getActiveCount() { + @Override + public int getActiveCount() { return this.delegate.getActiveCount(); } @@ -140,7 +152,8 @@ public class LazyTraceThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { super.afterPropertiesSet(); } - @Override public void initialize() { + @Override + public void initialize() { this.delegate.initialize(); } @@ -150,79 +163,103 @@ public class LazyTraceThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { super.shutdown(); } - @Override public Thread newThread(Runnable runnable) { + @Override + public Thread newThread(Runnable runnable) { return this.delegate.newThread(runnable); } - @Override public String getThreadNamePrefix() { + @Override + public String getThreadNamePrefix() { return this.delegate.getThreadNamePrefix(); } - @Override public void setThreadPriority(int threadPriority) { - this.delegate.setThreadPriority(threadPriority); + @Override + public void setThreadNamePrefix(String threadNamePrefix) { + this.delegate.setThreadNamePrefix(threadNamePrefix); } - @Override public int getThreadPriority() { + @Override + public int getThreadPriority() { return this.delegate.getThreadPriority(); } - @Override public void setDaemon(boolean daemon) { - this.delegate.setDaemon(daemon); + @Override + public void setThreadPriority(int threadPriority) { + this.delegate.setThreadPriority(threadPriority); } - @Override public boolean isDaemon() { + @Override + public boolean isDaemon() { return this.delegate.isDaemon(); } - @Override public void setThreadGroupName(String name) { + @Override + public void setDaemon(boolean daemon) { + this.delegate.setDaemon(daemon); + } + + @Override + public void setThreadGroupName(String name) { this.delegate.setThreadGroupName(name); } - @Override public void setThreadGroup(ThreadGroup threadGroup) { - this.delegate.setThreadGroup(threadGroup); - } - - @Override public ThreadGroup getThreadGroup() { + @Override + public ThreadGroup getThreadGroup() { return this.delegate.getThreadGroup(); } - @Override public Thread createThread(Runnable runnable) { + @Override + public void setThreadGroup(ThreadGroup threadGroup) { + this.delegate.setThreadGroup(threadGroup); + } + + @Override + public Thread createThread(Runnable runnable) { return this.delegate.createThread(runnable); } - @Override public void setCorePoolSize(int corePoolSize) { - this.delegate.setCorePoolSize(corePoolSize); - } - - @Override public int getCorePoolSize() { + @Override + public int getCorePoolSize() { return this.delegate.getCorePoolSize(); } - @Override public void setMaxPoolSize(int maxPoolSize) { - this.delegate.setMaxPoolSize(maxPoolSize); + @Override + public void setCorePoolSize(int corePoolSize) { + this.delegate.setCorePoolSize(corePoolSize); } - @Override public int getMaxPoolSize() { + @Override + public int getMaxPoolSize() { return this.delegate.getMaxPoolSize(); } - @Override public void setKeepAliveSeconds(int keepAliveSeconds) { - this.delegate.setKeepAliveSeconds(keepAliveSeconds); + @Override + public void setMaxPoolSize(int maxPoolSize) { + this.delegate.setMaxPoolSize(maxPoolSize); } - @Override public int getKeepAliveSeconds() { + @Override + public int getKeepAliveSeconds() { return this.delegate.getKeepAliveSeconds(); } - @Override public void setQueueCapacity(int queueCapacity) { + @Override + public void setKeepAliveSeconds(int keepAliveSeconds) { + this.delegate.setKeepAliveSeconds(keepAliveSeconds); + } + + @Override + public void setQueueCapacity(int queueCapacity) { this.delegate.setQueueCapacity(queueCapacity); } - @Override public void setAllowCoreThreadTimeOut(boolean allowCoreThreadTimeOut) { + @Override + public void setAllowCoreThreadTimeOut(boolean allowCoreThreadTimeOut) { this.delegate.setAllowCoreThreadTimeOut(allowCoreThreadTimeOut); } - @Override public void setTaskDecorator(TaskDecorator taskDecorator) { + @Override + public void setTaskDecorator(TaskDecorator taskDecorator) { this.delegate.setTaskDecorator(taskDecorator); } @@ -238,11 +275,13 @@ public class LazyTraceThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { try { this.spanNamer = this.beanFactory.getBean(SpanNamer.class); } - catch (NoSuchBeanDefinitionException e) { - log.warn("SpanNamer bean not found - will provide a manually created instance"); + catch (NoSuchBeanDefinitionException ex) { + log.warn( + "SpanNamer bean not found - will provide a manually created instance"); return new DefaultSpanNamer(); } } return this.spanNamer; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/SleuthAsyncProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/SleuthAsyncProperties.java index f4c06ff2c..eb35abacd 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/SleuthAsyncProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/SleuthAsyncProperties.java @@ -22,7 +22,7 @@ import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Settings for disable instrumentation of ThreadPoolTaskExecutors + * Settings for disable instrumentation of ThreadPoolTaskExecutors. * * @author Jesus Alonso * @since 2.1.0 @@ -32,8 +32,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; public class SleuthAsyncProperties { /** - * List of {@link java.util.concurrent.Executor} bean names that should - * be ignored and not wrapped in a trace representation + * List of {@link java.util.concurrent.Executor} bean names that should be ignored and + * not wrapped in a trace representation. */ private List ignoredBeans = Collections.emptyList(); @@ -44,4 +44,5 @@ public class SleuthAsyncProperties { public void setIgnoredBeans(List ignoredBeans) { this.ignoredBeans = ignoredBeans; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncAspect.java index 68996d2db..126238e91 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncAspect.java @@ -34,16 +34,17 @@ import org.springframework.util.ReflectionUtils; * * @author Marcin Grzejszczak * @since 1.0.0 - * * @see Tracer */ @Aspect public class TraceAsyncAspect { private static final String CLASS_KEY = "class"; + private static final String METHOD_KEY = "method"; private final Tracer tracer; + private final SpanNamer spanNamer; public TraceAsyncAspect(Tracer tracer, SpanNamer spanNamer) { @@ -59,11 +60,12 @@ public class TraceAsyncAspect { span = this.tracer.nextSpan(); } span = span.name(spanName); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { span.tag(CLASS_KEY, pjp.getTarget().getClass().getSimpleName()); span.tag(METHOD_KEY, pjp.getSignature().getName()); return pjp.proceed(); - } finally { + } + finally { span.finish(); } } @@ -76,8 +78,8 @@ public class TraceAsyncAspect { private Method getMethod(ProceedingJoinPoint pjp, Object object) { MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); - return ReflectionUtils - .findMethod(object.getClass(), method.getName(), method.getParameterTypes()); + return ReflectionUtils.findMethod(object.getClass(), method.getName(), + method.getParameterTypes()); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncListenableTaskExecutor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncListenableTaskExecutor.java index 508320e0a..77c191fd2 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncListenableTaskExecutor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncListenableTaskExecutor.java @@ -24,17 +24,18 @@ import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.util.concurrent.ListenableFuture; /** - * AsyncListenableTaskExecutor that wraps all Runnable / Callable tasks into - * their trace related representation + * AsyncListenableTaskExecutor that wraps all Runnable / Callable tasks into their trace + * related representation. * * @since 1.0.0 - * + * @author Marcin Grzejszczak * @see brave.propagation.CurrentTraceContext#wrap(Runnable) * @see brave.propagation.CurrentTraceContext#wrap(Callable) */ public class TraceAsyncListenableTaskExecutor implements AsyncListenableTaskExecutor { private final AsyncListenableTaskExecutor delegate; + private final Tracing tracing; TraceAsyncListenableTaskExecutor(AsyncListenableTaskExecutor delegate, @@ -45,17 +46,20 @@ public class TraceAsyncListenableTaskExecutor implements AsyncListenableTaskExec @Override public ListenableFuture submitListenable(Runnable task) { - return this.delegate.submitListenable(this.tracing.currentTraceContext().wrap(task)); + return this.delegate + .submitListenable(this.tracing.currentTraceContext().wrap(task)); } @Override public ListenableFuture submitListenable(Callable task) { - return this.delegate.submitListenable(this.tracing.currentTraceContext().wrap(task)); + return this.delegate + .submitListenable(this.tracing.currentTraceContext().wrap(task)); } @Override public void execute(Runnable task, long startTimeout) { - this.delegate.execute(this.tracing.currentTraceContext().wrap(task), startTimeout); + this.delegate.execute(this.tracing.currentTraceContext().wrap(task), + startTimeout); } @Override @@ -73,4 +77,4 @@ public class TraceAsyncListenableTaskExecutor implements AsyncListenableTaskExec this.delegate.execute(this.tracing.currentTraceContext().wrap(task)); } -} \ No newline at end of file +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceCallable.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceCallable.java index d40d1e4bf..6f92f1579 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceCallable.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceCallable.java @@ -16,56 +16,64 @@ package org.springframework.cloud.sleuth.instrument.async; -import brave.ScopedSpan; -import brave.Tracing; -import brave.propagation.TraceContext; import java.util.concurrent.Callable; +import brave.ScopedSpan; import brave.Tracer; +import brave.Tracing; +import brave.propagation.TraceContext; import org.springframework.cloud.sleuth.SpanNamer; /** - * Callable that passes Span between threads. The Span name is - * taken either from the passed value or from the {@link SpanNamer} - * interface. + * Callable that passes Span between threads. The Span name is taken either from the + * passed value or from the {@link SpanNamer} interface. * * @author Spencer Gibb * @author Marcin Grzejszczak + * @param - return type from callable * @since 1.0.0 */ public class TraceCallable implements Callable { /** - * Since we don't know the exact operation name we provide a default - * name for the Span + * 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 Callable delegate; + private final TraceContext parent; + private final String spanName; public TraceCallable(Tracing tracing, SpanNamer spanNamer, Callable delegate) { this(tracing, spanNamer, delegate, null); } - public TraceCallable(Tracing tracing, SpanNamer spanNamer, Callable delegate, String name) { + public TraceCallable(Tracing tracing, SpanNamer spanNamer, Callable delegate, + String name) { this.tracer = tracing.tracer(); this.delegate = delegate; this.parent = tracing.currentTraceContext().get(); this.spanName = name != null ? name : spanNamer.name(delegate, DEFAULT_SPAN_NAME); } - @Override public V call() throws Exception { - ScopedSpan span = this.tracer.startScopedSpanWithParent(this.spanName, this.parent); + @Override + public V call() throws Exception { + ScopedSpan span = this.tracer.startScopedSpanWithParent(this.spanName, + this.parent); try { return this.delegate.call(); - } catch (Exception | Error e) { - span.error(e); - throw e; - } finally { + } + catch (Exception | Error ex) { + span.error(ex); + throw ex; + } + finally { span.finish(); } } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceRunnable.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceRunnable.java index af0b8e1da..b5f5a65b3 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceRunnable.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceRunnable.java @@ -23,9 +23,8 @@ import brave.propagation.TraceContext; import org.springframework.cloud.sleuth.SpanNamer; /** - * Runnable that passes Span between threads. The Span name is - * taken either from the passed value or from the {@link SpanNamer} - * interface. + * Runnable that passes Span between threads. The Span name is taken either from the + * passed value or from the {@link SpanNamer} interface. * * @author Spencer Gibb * @author Marcin Grzejszczak @@ -34,21 +33,24 @@ import org.springframework.cloud.sleuth.SpanNamer; public class TraceRunnable implements Runnable { /** - * Since we don't know the exact operation name we provide a default - * name for the Span + * 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 Runnable delegate; + private final TraceContext parent; + private final String spanName; public TraceRunnable(Tracing tracing, SpanNamer spanNamer, Runnable delegate) { this(tracing, spanNamer, delegate, null); } - public TraceRunnable(Tracing tracing, SpanNamer spanNamer, Runnable delegate, String name) { + public TraceRunnable(Tracing tracing, SpanNamer spanNamer, Runnable delegate, + String name) { this.tracer = tracing.tracer(); this.delegate = delegate; this.parent = tracing.currentTraceContext().get(); @@ -57,14 +59,18 @@ public class TraceRunnable implements Runnable { @Override public void run() { - ScopedSpan span = this.tracer.startScopedSpanWithParent(this.spanName, this.parent); + ScopedSpan span = this.tracer.startScopedSpanWithParent(this.spanName, + this.parent); try { this.delegate.run(); - } catch (Exception | Error e) { + } + catch (Exception | Error e) { span.error(e); throw e; - } finally { + } + finally { span.finish(); } } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorService.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorService.java index 56b47bee5..eb9e033e5 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorService.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorService.java @@ -36,17 +36,24 @@ import org.springframework.cloud.sleuth.SpanNamer; * @since 1.0.0 */ public class TraceableExecutorService implements ExecutorService { + final ExecutorService delegate; + private final String spanName; + Tracing tracing; + SpanNamer spanNamer; + BeanFactory beanFactory; - public TraceableExecutorService(BeanFactory beanFactory, final ExecutorService delegate) { + public TraceableExecutorService(BeanFactory beanFactory, + final ExecutorService delegate) { this(beanFactory, delegate, null); } - public TraceableExecutorService(BeanFactory beanFactory, final ExecutorService delegate, String spanName) { + public TraceableExecutorService(BeanFactory beanFactory, + final ExecutorService delegate, String spanName) { this.delegate = delegate; this.beanFactory = beanFactory; this.spanName = spanName; @@ -54,7 +61,8 @@ public class TraceableExecutorService implements ExecutorService { @Override public void execute(Runnable command) { - final Runnable r = new TraceRunnable(tracing(), spanNamer(), command, this.spanName); + final Runnable r = new TraceRunnable(tracing(), spanNamer(), command, + this.spanName); this.delegate.execute(r); } @@ -79,7 +87,8 @@ public class TraceableExecutorService implements ExecutorService { } @Override - public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + public boolean awaitTermination(long timeout, TimeUnit unit) + throws InterruptedException { return this.delegate.awaitTermination(timeout, unit); } @@ -102,28 +111,32 @@ public class TraceableExecutorService implements ExecutorService { } @Override - public List> invokeAll(Collection> tasks) throws InterruptedException { + public List> invokeAll(Collection> tasks) + throws InterruptedException { return this.delegate.invokeAll(wrapCallableCollection(tasks)); } @Override - public List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) - throws InterruptedException { + public List> invokeAll(Collection> tasks, + long timeout, TimeUnit unit) throws InterruptedException { return this.delegate.invokeAll(wrapCallableCollection(tasks), timeout, unit); } @Override - public T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException { + public T invokeAny(Collection> tasks) + throws InterruptedException, ExecutionException { return this.delegate.invokeAny(wrapCallableCollection(tasks)); } @Override - public T invokeAny(Collection> tasks, long timeout, TimeUnit unit) + public T invokeAny(Collection> tasks, long timeout, + TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return this.delegate.invokeAny(wrapCallableCollection(tasks), timeout, unit); } - private Collection> wrapCallableCollection(Collection> tasks) { + private Collection> wrapCallableCollection( + Collection> tasks) { List> ts = new ArrayList<>(); for (Callable task : tasks) { if (!(task instanceof TraceCallable)) { @@ -146,4 +159,5 @@ public class TraceableExecutorService implements ExecutorService { } return this.spanNamer; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableScheduledExecutorService.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableScheduledExecutorService.java index 0fb22cf33..010a64859 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableScheduledExecutorService.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableScheduledExecutorService.java @@ -30,9 +30,11 @@ import org.springframework.beans.factory.BeanFactory; * @author Gaurav Rai Mazra * @since 1.0.0 */ -public class TraceableScheduledExecutorService extends TraceableExecutorService implements ScheduledExecutorService { +public class TraceableScheduledExecutorService extends TraceableExecutorService + implements ScheduledExecutorService { - public TraceableScheduledExecutorService(BeanFactory beanFactory, final ExecutorService delegate) { + public TraceableScheduledExecutorService(BeanFactory beanFactory, + final ExecutorService delegate) { super(beanFactory, delegate); } @@ -47,21 +49,26 @@ public class TraceableScheduledExecutorService extends TraceableExecutorService } @Override - public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit) { + public ScheduledFuture schedule(Callable callable, long delay, + TimeUnit unit) { Callable c = new TraceCallable<>(tracing(), spanNamer(), callable); return getScheduledExecutorService().schedule(c, delay, unit); } @Override - public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { + public ScheduledFuture scheduleAtFixedRate(Runnable command, long initialDelay, + long period, TimeUnit unit) { Runnable r = new TraceRunnable(tracing(), spanNamer(), command); - return getScheduledExecutorService().scheduleAtFixedRate(r, initialDelay, period, unit); + return getScheduledExecutorService().scheduleAtFixedRate(r, initialDelay, period, + unit); } @Override - public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { + public ScheduledFuture scheduleWithFixedDelay(Runnable command, long initialDelay, + long delay, TimeUnit unit) { Runnable r = new TraceRunnable(tracing(), spanNamer(), command); - return getScheduledExecutorService().scheduleWithFixedDelay(r, initialDelay, delay, unit); + return getScheduledExecutorService().scheduleWithFixedDelay(r, initialDelay, + delay, unit); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixAutoConfiguration.java index a341757ab..bad0a6875 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixAutoConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.instrument.hystrix; import brave.Tracing; +import com.netflix.hystrix.HystrixCommand; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -26,15 +27,13 @@ import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.context.annotation.Bean; 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}. + * {@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 @@ -44,7 +43,8 @@ import com.netflix.hystrix.HystrixCommand; @ConditionalOnProperty(value = "spring.sleuth.hystrix.strategy.enabled", matchIfMissing = true) public class SleuthHystrixAutoConfiguration { - @Bean SleuthHystrixConcurrencyStrategy sleuthHystrixConcurrencyStrategy(Tracing tracing, + @Bean + SleuthHystrixConcurrencyStrategy sleuthHystrixConcurrencyStrategy(Tracing tracing, SpanNamer spanNamer) { return new SleuthHystrixConcurrencyStrategy(tracing, spanNamer); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategy.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategy.java index 39237001e..f83e5be27 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategy.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategy.java @@ -49,11 +49,14 @@ import org.springframework.cloud.sleuth.instrument.async.TraceCallable; public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy { private static final String HYSTRIX_COMPONENT = "hystrix"; + private static final Log log = LogFactory .getLog(SleuthHystrixConcurrencyStrategy.class); private final Tracing tracing; + private final SpanNamer spanNamer; + private HystrixConcurrencyStrategy delegate; public SleuthHystrixConcurrencyStrategy(Tracing tracing, SpanNamer spanNamer) { @@ -83,8 +86,8 @@ public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher); HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy); } - catch (Exception e) { - log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e); + catch (Exception ex) { + log.error("Failed to register Sleuth Hystrix Concurrency Strategy", ex); } } @@ -92,10 +95,10 @@ public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy HystrixMetricsPublisher metricsPublisher, HystrixPropertiesStrategy propertiesStrategy) { if (log.isDebugEnabled()) { - log.debug("Current Hystrix plugins configuration is [" + "concurrencyStrategy [" - + this.delegate + "]," + "eventNotifier [" + eventNotifier + "]," - + "metricPublisher [" + metricsPublisher + "]," + "propertiesStrategy [" - + propertiesStrategy + "]," + "]"); + log.debug("Current Hystrix plugins configuration is [" + + "concurrencyStrategy [" + this.delegate + "]," + "eventNotifier [" + + eventNotifier + "]," + "metricPublisher [" + metricsPublisher + "]," + + "propertiesStrategy [" + propertiesStrategy + "]," + "]"); log.debug("Registering Sleuth Hystrix Concurrency Strategy."); } } @@ -110,8 +113,8 @@ public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy if (wrappedCallable instanceof TraceCallable) { return wrappedCallable; } - return new TraceCallable<>(this.tracing, this.spanNamer, - wrappedCallable, HYSTRIX_COMPONENT); + return new TraceCallable<>(this.tracing, this.spanNamer, wrappedCallable, + HYSTRIX_COMPONENT); } @Override @@ -140,4 +143,5 @@ public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy HystrixRequestVariableLifecycle rv) { return this.delegate.getRequestVariable(rv); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommand.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommand.java index 0d03d528c..76561e261 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommand.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommand.java @@ -23,24 +23,28 @@ import brave.Tracer; import com.netflix.hystrix.HystrixCommand; /** - * Abstraction over {@code HystrixCommand} that wraps command execution with Trace setting - * - * @see HystrixCommand - * @see Tracer + * Abstraction over {@code HystrixCommand} that wraps command execution with Trace setting. * + * @param - return type of Hystrix Command * @author Tomasz Nurkiewicz, 4financeIT * @author Marcin Grzejszczak * @author Spencer Gibb * @since 1.0.0 + * @see HystrixCommand + * @see Tracer */ public abstract class TraceCommand extends HystrixCommand { private static final String COMMAND_KEY = "commandKey"; + private static final String COMMAND_GROUP_KEY = "commandGroup"; + private static final String THREAD_POOL_KEY = "threadPoolKey"; + private static final String FALLBACK_METHOD_NAME_KEY = "fallbackMethodName"; private final Tracer tracer; + private final AtomicReference span; protected TraceCommand(Tracer tracer, Setter setter) { @@ -59,10 +63,12 @@ public abstract class TraceCommand extends HystrixCommand { Throwable throwable = null; try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { return doRun(); - } catch (Throwable t) { + } + catch (Throwable t) { throwable = t; throw t; - } finally { + } + finally { if (throwable == null) { span.finish(); this.span.set(null); @@ -73,12 +79,14 @@ public abstract class TraceCommand extends HystrixCommand { public abstract R doRun() throws Exception; - @Override protected R getFallback() { + @Override + protected R getFallback() { Span span = this.span.get(); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { span.tag(FALLBACK_METHOD_NAME_KEY, getFallbackMethodName()); return doGetFallback(); - } finally { + } + finally { span.finish(); this.span.set(null); } @@ -87,4 +95,5 @@ public abstract class TraceCommand extends HystrixCommand { public R doGetFallback() { return super.getFallback(); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagation.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagation.java index 3096fb865..c2fe78f58 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagation.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagation.java @@ -16,6 +16,7 @@ package org.springframework.cloud.sleuth.instrument.messaging; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -29,15 +30,16 @@ import org.springframework.messaging.support.NativeMessageHeaderAccessor; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.StringUtils; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.springframework.messaging.support.NativeMessageHeaderAccessor.NATIVE_HEADERS; - /** - * This always sets native headers in defence of STOMP issues discussed here + * This always sets native headers in defence of STOMP issues discussed here. + * + * @author Marcin Grzejszczak */ enum MessageHeaderPropagation implements Propagation.Setter, Propagation.Getter { + INSTANCE; private static final Log log = LogFactory.getLog(MessageHeaderPropagation.class); @@ -45,99 +47,24 @@ enum MessageHeaderPropagation private static final Map LEGACY_HEADER_MAPPING = new HashMap<>(); private static final String TRACE_ID_NAME = "X-B3-TraceId"; + private static final String SPAN_ID_NAME = "X-B3-SpanId"; + private static final String PARENT_SPAN_ID_NAME = "X-B3-ParentSpanId"; + private static final String SAMPLED_NAME = "X-B3-Sampled"; + private static final String FLAGS_NAME = "X-B3-Flags"; static { LEGACY_HEADER_MAPPING.put(TRACE_ID_NAME, TraceMessageHeaders.TRACE_ID_NAME); LEGACY_HEADER_MAPPING.put(SPAN_ID_NAME, TraceMessageHeaders.SPAN_ID_NAME); - LEGACY_HEADER_MAPPING.put(PARENT_SPAN_ID_NAME, TraceMessageHeaders.PARENT_ID_NAME); + LEGACY_HEADER_MAPPING.put(PARENT_SPAN_ID_NAME, + TraceMessageHeaders.PARENT_ID_NAME); LEGACY_HEADER_MAPPING.put(SAMPLED_NAME, TraceMessageHeaders.SAMPLED_NAME); LEGACY_HEADER_MAPPING.put(FLAGS_NAME, TraceMessageHeaders.SPAN_FLAGS_NAME); } - @Override public void put(MessageHeaderAccessor accessor, String key, String value) { - try { - doPut(accessor, key, value); - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("An exception happened when we tried to retrieve the [" + key + "] from message", e); - } - } - String legacyKey = LEGACY_HEADER_MAPPING.get(key); - if (legacyKey != null) { - doPut(accessor, legacyKey, value); - } - } - - private void doPut(MessageHeaderAccessor accessor, String key, String value) { - accessor.setHeader(key, value); - if (accessor instanceof NativeMessageHeaderAccessor) { - NativeMessageHeaderAccessor nativeAccessor = (NativeMessageHeaderAccessor) accessor; - nativeAccessor.setNativeHeader(key, value); - } - else { - Object nativeHeaders = accessor.getHeader(NATIVE_HEADERS); - if (nativeHeaders == null) { - accessor.setHeader(NATIVE_HEADERS, - nativeHeaders = new LinkedMultiValueMap<>()); - } - if (nativeHeaders instanceof Map) { - ((Map) nativeHeaders).put(key, Collections.singletonList(value)); - } - } - } - - @Override public String get(MessageHeaderAccessor accessor, String key) { - try { - String value = doGet(accessor, key); - if (StringUtils.hasText(value)) { - return value; - } - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("An exception happened when we tried to retrieve the [" + key + "] from message", e); - } - } - return legacyValue(accessor, key); - } - - private String legacyValue(MessageHeaderAccessor accessor, String key) { - String legacyKey = LEGACY_HEADER_MAPPING.get(key); - if (legacyKey != null) { - return doGet(accessor, legacyKey); - } - return null; - } - - private String doGet(MessageHeaderAccessor accessor, String key) { - if (accessor instanceof NativeMessageHeaderAccessor) { - NativeMessageHeaderAccessor nativeAccessor = (NativeMessageHeaderAccessor) accessor; - String result = nativeAccessor.getFirstNativeHeader(key); - if (result != null) { - return result; - } - } else { - Object nativeHeaders = accessor.getHeader(NATIVE_HEADERS); - if (nativeHeaders instanceof Map) { - Object result = ((Map) nativeHeaders).get(key); - if (result instanceof List && !((List) result).isEmpty()) { - return String.valueOf(((List) result).get(0)); - } - } - } - Object result = accessor.getHeader(key); - if (result != null) { - if (result instanceof byte[]) { - return new String((byte[]) result, UTF_8); - } - return result.toString(); - } - return null; - } - static Map propagationHeaders(Map headers, List propagationHeaders) { Map headersToCopy = new HashMap<>(); @@ -156,8 +83,9 @@ enum MessageHeaderPropagation if (accessor instanceof NativeMessageHeaderAccessor) { NativeMessageHeaderAccessor nativeAccessor = (NativeMessageHeaderAccessor) accessor; nativeAccessor.removeNativeHeader(keyToRemove); - } else { - Object nativeHeaders = accessor.getHeader(NATIVE_HEADERS); + } + else { + Object nativeHeaders = accessor.getHeader(NativeMessageHeaderAccessor.NATIVE_HEADERS); if (nativeHeaders instanceof Map) { ((Map) nativeHeaders).remove(keyToRemove); } @@ -165,7 +93,96 @@ enum MessageHeaderPropagation } } - @Override public String toString() { + @Override + public void put(MessageHeaderAccessor accessor, String key, String value) { + try { + doPut(accessor, key, value); + } + catch (Exception ex) { + if (log.isDebugEnabled()) { + log.debug("An exception happened when we tried to retrieve the [" + key + + "] from message", ex); + } + } + String legacyKey = LEGACY_HEADER_MAPPING.get(key); + if (legacyKey != null) { + doPut(accessor, legacyKey, value); + } + } + + private void doPut(MessageHeaderAccessor accessor, String key, String value) { + accessor.setHeader(key, value); + if (accessor instanceof NativeMessageHeaderAccessor) { + NativeMessageHeaderAccessor nativeAccessor = (NativeMessageHeaderAccessor) accessor; + nativeAccessor.setNativeHeader(key, value); + } + else { + Object nativeHeaders = accessor.getHeader(NativeMessageHeaderAccessor.NATIVE_HEADERS); + if (nativeHeaders == null) { + accessor.setHeader(NativeMessageHeaderAccessor.NATIVE_HEADERS, + nativeHeaders = new LinkedMultiValueMap<>()); + } + if (nativeHeaders instanceof Map) { + ((Map) nativeHeaders).put(key, Collections.singletonList(value)); + } + } + } + + @Override + public String get(MessageHeaderAccessor accessor, String key) { + try { + String value = doGet(accessor, key); + if (StringUtils.hasText(value)) { + return value; + } + } + catch (Exception ex) { + if (log.isDebugEnabled()) { + log.debug("An exception happened when we tried to retrieve the [" + key + + "] from message", ex); + } + } + return legacyValue(accessor, key); + } + + private String legacyValue(MessageHeaderAccessor accessor, String key) { + String legacyKey = LEGACY_HEADER_MAPPING.get(key); + if (legacyKey != null) { + return doGet(accessor, legacyKey); + } + return null; + } + + private String doGet(MessageHeaderAccessor accessor, String key) { + if (accessor instanceof NativeMessageHeaderAccessor) { + NativeMessageHeaderAccessor nativeAccessor = (NativeMessageHeaderAccessor) accessor; + String result = nativeAccessor.getFirstNativeHeader(key); + if (result != null) { + return result; + } + } + else { + Object nativeHeaders = accessor.getHeader(NativeMessageHeaderAccessor.NATIVE_HEADERS); + if (nativeHeaders instanceof Map) { + Object result = ((Map) nativeHeaders).get(key); + if (result instanceof List && !((List) result).isEmpty()) { + return String.valueOf(((List) result).get(0)); + } + } + } + Object result = accessor.getHeader(key); + if (result != null) { + if (result instanceof byte[]) { + return new String((byte[]) result, StandardCharsets.UTF_8); + } + return result.toString(); + } + return null; + } + + @Override + public String toString() { return "MessageHeaderPropagation{}"; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/OnMessagingEnabled.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/OnMessagingEnabled.java index 4eac04af4..4b4127999 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/OnMessagingEnabled.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/OnMessagingEnabled.java @@ -25,6 +25,8 @@ import java.lang.annotation.Target; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; /** + * Verifies if messaging property was enabled. + * * @author Marcin Grzejszczak * @since 2.0.0 */ @@ -33,4 +35,5 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @Documented @ConditionalOnProperty(value = "spring.sleuth.messaging.enabled", matchIfMissing = true) @interface OnMessagingEnabled { + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SleuthMessagingProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SleuthMessagingProperties.java index 3c6cd32c8..dd534bede 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SleuthMessagingProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SleuthMessagingProperties.java @@ -19,6 +19,8 @@ package org.springframework.cloud.sleuth.instrument.messaging; import org.springframework.boot.context.properties.ConfigurationProperties; /** + * Properties for messaging + * * @author Marcin Grzejszczak * @since 2.0.0 */ @@ -45,7 +47,13 @@ public class SleuthMessagingProperties { this.messaging = messaging; } + /** + * Properties for Spring Integration + * + * @author Marcin Grzejszczak + */ public static class Integration { + /** * An array of patterns against which channel names will be matched. * @see org.springframework.integration.config.GlobalChannelInterceptor#patterns(). @@ -54,7 +62,7 @@ public class SleuthMessagingProperties { private String[] patterns = new String[] { "!hystrixStreamOutput*", "*" }; /** - * Enable Spring Integration sleuth instrumentation + * Enable Spring Integration sleuth instrumentation. */ private boolean enabled; @@ -73,15 +81,34 @@ public class SleuthMessagingProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } + /** + * Generic messaging properties. + * + * @author Marcin Grzejszczak + */ public static class Messaging { + + /** + * Should messaging be turned on. + */ private boolean enabled; + /** + * Rabbit related properties. + */ private Rabbit rabbit = new Rabbit(); + /** + * Kafka related properties. + */ private Kafka kafka = new Kafka(); + /** + * JMS related properties. + */ private Jms jms = new Jms(); public boolean isEnabled() { @@ -115,9 +142,11 @@ public class SleuthMessagingProperties { public void setJms(Jms jms) { this.jms = jms; } + } public static class Rabbit { + private boolean enabled; private String remoteServiceName = "rabbitmq"; @@ -137,9 +166,11 @@ public class SleuthMessagingProperties { public void setRemoteServiceName(String remoteServiceName) { this.remoteServiceName = remoteServiceName; } + } public static class Kafka { + private boolean enabled; private String remoteServiceName = "kafka"; @@ -159,9 +190,11 @@ public class SleuthMessagingProperties { public void setRemoteServiceName(String remoteServiceName) { this.remoteServiceName = remoteServiceName; } + } public static class Jms { + private boolean enabled; private String remoteServiceName = "jms"; @@ -181,5 +214,7 @@ public class SleuthMessagingProperties { public void setRemoteServiceName(String remoteServiceName) { this.remoteServiceName = remoteServiceName; } + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessageHeaders.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessageHeaders.java index d47165f8e..473794b5a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessageHeaders.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessageHeaders.java @@ -27,11 +27,18 @@ package org.springframework.cloud.sleuth.instrument.messaging; public class TraceMessageHeaders { public static final String SPAN_ID_NAME = "spanId"; + public static final String SAMPLED_NAME = "spanSampled"; + public static final String PARENT_ID_NAME = "spanParentSpanId"; + public static final String TRACE_ID_NAME = "spanTraceId"; + public static final String SPAN_NAME_NAME = "spanName"; + public static final String SPAN_FLAGS_NAME = "spanFlags"; - private TraceMessageHeaders() {} + private TraceMessageHeaders() { + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfiguration.java index 095407d14..e6d2a60c7 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfiguration.java @@ -63,8 +63,7 @@ import org.springframework.util.ReflectionUtils; /** * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration - * Auto-configuration} that registers a tracing instrumentation of - * messaging components. + * Auto-configuration} that registers a tracing instrumentation of messaging components. * * @author Marcin Grzejszczak * @since 2.0.0 @@ -80,21 +79,25 @@ public class TraceMessagingAutoConfiguration { @ConditionalOnProperty(value = "spring.sleuth.messaging.rabbit.enabled", matchIfMissing = true) @ConditionalOnClass(RabbitTemplate.class) protected static class SleuthRabbitConfiguration { + + @Bean + // for tests + @ConditionalOnMissingBean + static SleuthRabbitBeanPostProcessor sleuthRabbitBeanPostProcessor( + BeanFactory beanFactory) { + return new SleuthRabbitBeanPostProcessor(beanFactory); + } + @Bean @ConditionalOnMissingBean SpringRabbitTracing springRabbitTracing(Tracing tracing, SleuthMessagingProperties properties) { return SpringRabbitTracing.newBuilder(tracing) - .remoteServiceName(properties.getMessaging().getRabbit().getRemoteServiceName()) + .remoteServiceName( + properties.getMessaging().getRabbit().getRemoteServiceName()) .build(); } - @Bean - // for tests - @ConditionalOnMissingBean - static SleuthRabbitBeanPostProcessor sleuthRabbitBeanPostProcessor(BeanFactory beanFactory) { - return new SleuthRabbitBeanPostProcessor(beanFactory); - } } @Configuration @@ -105,9 +108,9 @@ public class TraceMessagingAutoConfiguration { @Bean @ConditionalOnMissingBean KafkaTracing kafkaTracing(Tracing tracing, SleuthMessagingProperties properties) { - return KafkaTracing - .newBuilder(tracing) - .remoteServiceName(properties.getMessaging().getKafka().getRemoteServiceName()) + return KafkaTracing.newBuilder(tracing) + .remoteServiceName( + properties.getMessaging().getKafka().getRemoteServiceName()) .build(); } @@ -117,6 +120,7 @@ public class TraceMessagingAutoConfiguration { SleuthKafkaAspect sleuthKafkaAspect(KafkaTracing kafkaTracing, Tracer tracer) { return new SleuthKafkaAspect(kafkaTracing, tracer); } + } @Configuration @@ -128,48 +132,56 @@ public class TraceMessagingAutoConfiguration { @ConditionalOnMissingBean JmsTracing jmsTracing(Tracing tracing, SleuthMessagingProperties properties) { return JmsTracing.newBuilder(tracing) - .remoteServiceName(properties.getMessaging().getJms().getRemoteServiceName()) + .remoteServiceName( + properties.getMessaging().getJms().getRemoteServiceName()) .build(); } @Bean // for tests @ConditionalOnMissingBean - TracingConnectionFactoryBeanPostProcessor tracingConnectionFactoryBeanPostProcessor(BeanFactory beanFactory) { + TracingConnectionFactoryBeanPostProcessor tracingConnectionFactoryBeanPostProcessor( + BeanFactory beanFactory) { return new TracingConnectionFactoryBeanPostProcessor(beanFactory); } /** Choose the tracing endpoint registry */ @Bean - TracingJmsListenerEndpointRegistry tracingJmsListenerEndpointRegistry(JmsTracing jmsTracing, CurrentTraceContext current) { + TracingJmsListenerEndpointRegistry tracingJmsListenerEndpointRegistry( + JmsTracing jmsTracing, CurrentTraceContext current) { return new TracingJmsListenerEndpointRegistry(jmsTracing, current); } /** Setup the tracing endpoint registry */ @Bean - JmsListenerConfigurer configureTracing(TracingJmsListenerEndpointRegistry registry) { + JmsListenerConfigurer configureTracing( + TracingJmsListenerEndpointRegistry registry) { return registrar -> registrar.setEndpointRegistry(registry); } + } + } class SleuthRabbitBeanPostProcessor implements BeanPostProcessor { private final BeanFactory beanFactory; + private SpringRabbitTracing tracing; SleuthRabbitBeanPostProcessor(BeanFactory beanFactory) { this.beanFactory = beanFactory; } - @Override public Object postProcessBeforeInitialization(Object bean, String beanName) + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof RabbitTemplate) { - return rabbitTracing() - .decorateRabbitTemplate((RabbitTemplate) bean); - } else if (bean instanceof SimpleRabbitListenerContainerFactory) { - return rabbitTracing() - .decorateSimpleRabbitListenerContainerFactory((SimpleRabbitListenerContainerFactory) bean); + return rabbitTracing().decorateRabbitTemplate((RabbitTemplate) bean); + } + else if (bean instanceof SimpleRabbitListenerContainerFactory) { + return rabbitTracing().decorateSimpleRabbitListenerContainerFactory( + (SimpleRabbitListenerContainerFactory) bean); } return bean; } @@ -180,31 +192,35 @@ class SleuthRabbitBeanPostProcessor implements BeanPostProcessor { } return this.tracing; } + } @Aspect class SleuthKafkaAspect { private static final Log log = LogFactory.getLog(SleuthKafkaAspect.class); - + final Field recordMessageConverter; private final KafkaTracing kafkaTracing; private final Tracer tracer; - final Field recordMessageConverter; SleuthKafkaAspect(KafkaTracing kafkaTracing, Tracer tracer) { this.kafkaTracing = kafkaTracing; this.tracer = tracer; - this.recordMessageConverter = ReflectionUtils.findField(MessagingMessageListenerAdapter.class, "recordMessageConverter"); + this.recordMessageConverter = ReflectionUtils.findField( + MessagingMessageListenerAdapter.class, "recordMessageConverter"); } @Pointcut("execution(public * org.springframework.kafka.core.ProducerFactory.createProducer(..))") - private void anyProducerFactory() { } // NOSONAR + private void anyProducerFactory() { + } // NOSONAR @Pointcut("execution(public * org.springframework.kafka.core.ConsumerFactory.createConsumer(..))") - private void anyConsumerFactory() { } // NOSONAR + private void anyConsumerFactory() { + } // NOSONAR @Pointcut("execution(public * org.springframework.kafka.config.KafkaListenerContainerFactory.createListenerContainer(..))") - private void anyCreateListenerContainer() { } // NOSONAR + private void anyCreateListenerContainer() { + } // NOSONAR @Around("anyProducerFactory()") public Object wrapProducerFactory(ProceedingJoinPoint pjp) throws Throwable { @@ -219,23 +235,28 @@ class SleuthKafkaAspect { } @Around("anyCreateListenerContainer()") - public Object wrapListenerContainerCreation(ProceedingJoinPoint pjp) throws Throwable { + public Object wrapListenerContainerCreation(ProceedingJoinPoint pjp) + throws Throwable { MessageListenerContainer listener = (MessageListenerContainer) pjp.proceed(); if (listener instanceof AbstractMessageListenerContainer) { AbstractMessageListenerContainer container = (AbstractMessageListenerContainer) listener; - Object someMessageListener = container.getContainerProperties().getMessageListener(); + Object someMessageListener = container.getContainerProperties() + .getMessageListener(); if (someMessageListener == null) { if (log.isDebugEnabled()) { log.debug("No message listener to wrap. Proceeding"); } - } else if (someMessageListener instanceof MessageListener) { + } + else if (someMessageListener instanceof MessageListener) { container.setupMessageListener(createProxy(someMessageListener)); - } else { + } + else { if (log.isDebugEnabled()) { log.debug("ATM we don't support Batch message listeners"); } } - } else { + } + else { if (log.isDebugEnabled()) { log.debug("Can't wrap this listener. Proceeding"); } @@ -247,17 +268,22 @@ class SleuthKafkaAspect { Object createProxy(Object bean) { ProxyFactoryBean factory = new ProxyFactoryBean(); factory.setProxyTargetClass(true); - factory.addAdvice(new MessageListenerMethodInterceptor(this.kafkaTracing, this.tracer)); + factory.addAdvice( + new MessageListenerMethodInterceptor(this.kafkaTracing, this.tracer)); factory.setTarget(bean); return factory.getObject(); } + } -class MessageListenerMethodInterceptor implements MethodInterceptor { +class MessageListenerMethodInterceptor + implements MethodInterceptor { - private static final Log log = LogFactory.getLog(MessageListenerMethodInterceptor.class); + private static final Log log = LogFactory + .getLog(MessageListenerMethodInterceptor.class); private final KafkaTracing kafkaTracing; + private final Tracer tracer; MessageListenerMethodInterceptor(KafkaTracing kafkaTracing, Tracer tracer) { @@ -265,29 +291,35 @@ class MessageListenerMethodInterceptor implements Met this.tracer = tracer; } - @Override public Object invoke(MethodInvocation invocation) - throws Throwable { + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { if (!"onMessage".equals(invocation.getMethod().getName())) { return invocation.proceed(); } Object[] arguments = invocation.getArguments(); - Optional record = Arrays.stream(arguments).filter(o -> o instanceof ConsumerRecord).findFirst(); + Optional record = Arrays.stream(arguments) + .filter(o -> o instanceof ConsumerRecord).findFirst(); if (!record.isPresent()) { return invocation.proceed(); } if (log.isDebugEnabled()) { log.debug("Wrapping onMessage call"); } - Span span = this.kafkaTracing.nextSpan((ConsumerRecord) record.get()).name("on-message").start(); + Span span = this.kafkaTracing.nextSpan((ConsumerRecord) record.get()) + .name("on-message").start(); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { return invocation.proceed(); - } catch (RuntimeException | Error e) { + } + catch (RuntimeException | Error e) { String message = e.getMessage(); - if (message == null) message = e.getClass().getSimpleName(); + if (message == null) + message = e.getClass().getSimpleName(); span.tag("error", message); throw e; - } finally { + } + finally { span.finish(); } } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceSpringIntegrationAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceSpringIntegrationAutoConfiguration.java index de4ab8705..0512b09e8 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceSpringIntegrationAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceSpringIntegrationAutoConfiguration.java @@ -38,7 +38,6 @@ import org.springframework.messaging.support.MessageHeaderAccessor; * * @author Spencer Gibb * @since 1.0.0 - * * @see TracingChannelInterceptor */ @Configuration @@ -52,9 +51,9 @@ public class TraceSpringIntegrationAutoConfiguration { @Bean public GlobalChannelInterceptorWrapper tracingGlobalChannelInterceptorWrapper( - TracingChannelInterceptor interceptor, - SleuthMessagingProperties properties) { - GlobalChannelInterceptorWrapper wrapper = new GlobalChannelInterceptorWrapper(interceptor); + TracingChannelInterceptor interceptor, SleuthMessagingProperties properties) { + GlobalChannelInterceptorWrapper wrapper = new GlobalChannelInterceptorWrapper( + interceptor); wrapper.setPatterns(properties.getIntegration().getPatterns()); return wrapper; } @@ -63,7 +62,8 @@ public class TraceSpringIntegrationAutoConfiguration { TracingChannelInterceptor traceChannelInterceptor(Tracing tracing, Propagation.Setter traceMessagePropagationSetter, Propagation.Getter traceMessagePropagationGetter) { - return new TracingChannelInterceptor(tracing, traceMessagePropagationSetter, traceMessagePropagationGetter); + return new TracingChannelInterceptor(tracing, traceMessagePropagationSetter, + traceMessagePropagationGetter); } @Bean diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptor.java index 34cf4c161..e658ceaba 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptor.java @@ -45,39 +45,41 @@ import org.springframework.messaging.support.MessageHeaderAccessor; import org.springframework.util.ClassUtils; /** - * This starts and propagates {@link Span.Kind#PRODUCER} span for each message sent (via native - * headers. It also extracts or creates a {@link Span.Kind#CONSUMER} span for each message - * received. This span is injected onto each message so it becomes the parent when a handler later - * calls {@link MessageHandler#handleMessage(Message)}, or a another processing library calls {@link #nextSpan(Message)}. + * This starts and propagates {@link Span.Kind#PRODUCER} span for each message sent (via + * native headers. It also extracts or creates a {@link Span.Kind#CONSUMER} span for each + * message received. This span is injected onto each message so it becomes the parent when + * a handler later calls {@link MessageHandler#handleMessage(Message)}, or a another + * processing library calls {@link #nextSpan(Message)}. *

    - *

    This implementation uses {@link ThreadLocalSpan} to propagate context between callbacks. This - * is an alternative to {@code ThreadStatePropagationChannelInterceptor} which is less sensitive - * to message manipulation by other interceptors. + *

    + * This implementation uses {@link ThreadLocalSpan} to propagate context between + * callbacks. This is an alternative to {@code ThreadStatePropagationChannelInterceptor} + * which is less sensitive to message manipulation by other interceptors. */ public final class TracingChannelInterceptor extends ChannelInterceptorAdapter implements ExecutorChannelInterceptor { private static final Log log = LogFactory.getLog(TracingChannelInterceptor.class); + /** * Using the literal "broker" until we come up with a better solution. * - *

    If the message originated from a binder (consumer binding), there will be different - * headers present (e.g. "KafkaHeaders.RECEIVED_TOPIC" Vs. "AmqpHeaders.CONSUMER_QUEUE" - * (unless the application removes them before sending). These don't represent the broker, - * rather a queue, and in any case the heuristics are not great. At least we might be able - * to tell if this is rabbit or not (ex how spring-rabbit works). We need to think this - * through before making an api, possibly experimenting. + *

    + * If the message originated from a binder (consumer binding), there will be different + * headers present (e.g. "KafkaHeaders.RECEIVED_TOPIC" Vs. + * "AmqpHeaders.CONSUMER_QUEUE" (unless the application removes them before sending). + * These don't represent the broker, rather a queue, and in any case the heuristics + * are not great. At least we might be able to tell if this is rabbit or not (ex how + * spring-rabbit works). We need to think this through before making an api, possibly + * experimenting. * - *

    If the app is outbound only (producer), there's no indication of what type the + *

    + * If the app is outbound only (producer), there's no indication of what type the * destination broker is. This may hint at a non-manual solution being overwriting the - * remoteServiceName later, similar to how servlet instrumentation lazy set "http.route". + * remoteServiceName later, similar to how servlet instrumentation lazy set + * "http.route". */ private static final String REMOTE_SERVICE_NAME = "broker"; - - public static TracingChannelInterceptor create(Tracing tracing) { - return new TracingChannelInterceptor(tracing); - } - final Tracing tracing; final Tracer tracer; final ThreadLocalSpan threadLocalSpan; @@ -88,31 +90,35 @@ public final class TracingChannelInterceptor extends ChannelInterceptorAdapter @Autowired TracingChannelInterceptor(Tracing tracing) { - this(tracing, MessageHeaderPropagation.INSTANCE, MessageHeaderPropagation.INSTANCE); + this(tracing, MessageHeaderPropagation.INSTANCE, + MessageHeaderPropagation.INSTANCE); } - TracingChannelInterceptor(Tracing tracing, Propagation.Setter setter, + TracingChannelInterceptor(Tracing tracing, + Propagation.Setter setter, Propagation.Getter getter) { this.tracing = tracing; this.tracer = tracing.tracer(); this.threadLocalSpan = ThreadLocalSpan.create(this.tracer); - this.injector = tracing.propagation() - .injector(setter); - this.extractor = tracing.propagation() - .extractor(getter); + this.injector = tracing.propagation().injector(setter); + this.extractor = tracing.propagation().extractor(getter); this.integrationObjectSupportPresent = ClassUtils.isPresent( - "org.springframework.integration.context.IntegrationObjectSupport", - null); + "org.springframework.integration.context.IntegrationObjectSupport", null); this.hasDirectChannelClass = ClassUtils .isPresent("org.springframework.integration.channel.DirectChannel", null); } + public static TracingChannelInterceptor create(Tracing tracing) { + return new TracingChannelInterceptor(tracing); + } + /** - * Use this to create a span for processing the given message. Note: the result has no name and is - * not started. + * Use this to create a span for processing the given message. Note: the result has no + * name and is not started. *

    - *

    This creates a child from identifiers extracted from the message headers, or a new span if - * one couldn't be extracted. + *

    + * This creates a child from identifiers extracted from the message headers, or a new + * span if one couldn't be extracted. */ public Span nextSpan(Message message) { MessageHeaderAccessor headers = mutableHeaderAccessor(message); @@ -131,7 +137,8 @@ public final class TracingChannelInterceptor extends ChannelInterceptorAdapter /** * Starts and propagates {@link Span.Kind#PRODUCER} span for each message sent. */ - @Override public Message preSend(Message message, MessageChannel channel) { + @Override + public Message preSend(Message message, MessageChannel channel) { if (emptyMessage(message)) { return message; } @@ -139,8 +146,8 @@ public final class TracingChannelInterceptor extends ChannelInterceptorAdapter MessageHeaderAccessor headers = mutableHeaderAccessor(retrievedMessage); TraceContextOrSamplingFlags extracted = this.extractor.extract(headers); Span span = this.threadLocalSpan.next(extracted); - MessageHeaderPropagation - .removeAnyTraceHeaders(headers, this.tracing.propagation().keys()); + MessageHeaderPropagation.removeAnyTraceHeaders(headers, + this.tracing.propagation().keys()); this.injector.inject(span.context(), headers); if (!span.isNoop()) { span.kind(Span.Kind.PRODUCER).name("send").start(); @@ -157,30 +164,36 @@ public final class TracingChannelInterceptor extends ChannelInterceptorAdapter return outputMessage; } - private Message outputMessage(Message originalMessage, Message retrievedMessage, MessageHeaderAccessor additionalHeaders) { - MessageHeaderAccessor headers = MessageHeaderAccessor.getMutableAccessor(originalMessage); + private Message outputMessage(Message originalMessage, + Message retrievedMessage, MessageHeaderAccessor additionalHeaders) { + MessageHeaderAccessor headers = MessageHeaderAccessor + .getMutableAccessor(originalMessage); if (originalMessage.getPayload() instanceof MessagingException) { - headers.copyHeaders(MessageHeaderPropagation.propagationHeaders(additionalHeaders.getMessageHeaders(), + headers.copyHeaders(MessageHeaderPropagation.propagationHeaders( + additionalHeaders.getMessageHeaders(), this.tracing.propagation().keys())); return new ErrorMessage((MessagingException) originalMessage.getPayload(), - isWebSockets(headers) ? headers.getMessageHeaders() : new MessageHeaders(headers.getMessageHeaders())); + isWebSockets(headers) ? headers.getMessageHeaders() + : new MessageHeaders(headers.getMessageHeaders())); } headers.copyHeaders(additionalHeaders.getMessageHeaders()); return new GenericMessage<>(retrievedMessage.getPayload(), - isWebSockets(headers) ? headers.getMessageHeaders() : new MessageHeaders(headers.getMessageHeaders())); + isWebSockets(headers) ? headers.getMessageHeaders() + : new MessageHeaders(headers.getMessageHeaders())); } private boolean isWebSockets(MessageHeaderAccessor headerAccessor) { - return headerAccessor.getMessageHeaders().containsKey("stompCommand") || - headerAccessor.getMessageHeaders().containsKey("simpMessageType"); + return headerAccessor.getMessageHeaders().containsKey("stompCommand") + || headerAccessor.getMessageHeaders().containsKey("simpMessageType"); } private boolean isDirectChannel(MessageChannel channel) { - return this.hasDirectChannelClass && - DirectChannel.class.isAssignableFrom(AopUtils.getTargetClass(channel)); + return this.hasDirectChannelClass + && DirectChannel.class.isAssignableFrom(AopUtils.getTargetClass(channel)); } - @Override public void afterSendCompletion(Message message, MessageChannel channel, + @Override + public void afterSendCompletion(Message message, MessageChannel channel, boolean sent, Exception ex) { if (emptyMessage(message)) { return; @@ -189,24 +202,26 @@ public final class TracingChannelInterceptor extends ChannelInterceptorAdapter afterMessageHandled(message, channel, null, ex); } if (log.isDebugEnabled()) { - log.debug("Will finish the current span after completion " + this.tracer.currentSpan()); + log.debug("Will finish the current span after completion " + + this.tracer.currentSpan()); } finishSpan(ex); } /** - * This starts a consumer span as a child of the incoming message or the current trace context, - * placing it in scope until the receive completes. + * This starts a consumer span as a child of the incoming message or the current trace + * context, placing it in scope until the receive completes. */ - @Override public Message postReceive(Message message, MessageChannel channel) { + @Override + public Message postReceive(Message message, MessageChannel channel) { if (emptyMessage(message)) { return message; } MessageHeaderAccessor headers = mutableHeaderAccessor(message); TraceContextOrSamplingFlags extracted = this.extractor.extract(headers); Span span = this.threadLocalSpan.next(extracted); - MessageHeaderPropagation - .removeAnyTraceHeaders(headers, this.tracing.propagation().keys()); + MessageHeaderPropagation.removeAnyTraceHeaders(headers, + this.tracing.propagation().keys()); this.injector.inject(span.context(), headers); if (!span.isNoop()) { span.kind(Span.Kind.CONSUMER).name("receive").start(); @@ -227,16 +242,18 @@ public final class TracingChannelInterceptor extends ChannelInterceptorAdapter return; } if (log.isDebugEnabled()) { - log.debug("Will finish the current span after receive completion " + this.tracer.currentSpan()); + log.debug("Will finish the current span after receive completion " + + this.tracer.currentSpan()); } finishSpan(ex); } /** - * This starts a consumer span as a child of the incoming message or the current trace context. - * It then creates a span for the handler, placing it in scope. + * This starts a consumer span as a child of the incoming message or the current trace + * context. It then creates a span for the handler, placing it in scope. */ - @Override public Message beforeHandle(Message message, MessageChannel channel, + @Override + public Message beforeHandle(Message message, MessageChannel channel, MessageHandler handler) { if (emptyMessage(message)) { return message; @@ -252,29 +269,34 @@ public final class TracingChannelInterceptor extends ChannelInterceptorAdapter consumerSpan.finish(); } // create and scope a span for the message processor - this.threadLocalSpan.next(TraceContextOrSamplingFlags.create(consumerSpan.context())) + this.threadLocalSpan + .next(TraceContextOrSamplingFlags.create(consumerSpan.context())) .name("handle").start(); - // remove any trace headers, but don't re-inject as we are synchronously processing the + // remove any trace headers, but don't re-inject as we are synchronously + // processing the // message and can rely on scoping to access this span later. - MessageHeaderPropagation - .removeAnyTraceHeaders(headers, this.tracing.propagation().keys()); + MessageHeaderPropagation.removeAnyTraceHeaders(headers, + this.tracing.propagation().keys()); if (log.isDebugEnabled()) { log.debug("Created a new span in before handle" + consumerSpan); } if (message instanceof ErrorMessage) { - return new ErrorMessage((Throwable) message.getPayload(), headers.getMessageHeaders()); + return new ErrorMessage((Throwable) message.getPayload(), + headers.getMessageHeaders()); } headers.setImmutable(); return new GenericMessage<>(message.getPayload(), headers.getMessageHeaders()); } - @Override public void afterMessageHandled(Message message, MessageChannel channel, + @Override + public void afterMessageHandled(Message message, MessageChannel channel, MessageHandler handler, Exception ex) { if (emptyMessage(message)) { return; } if (log.isDebugEnabled()) { - log.debug("Will finish the current span after message handled " + this.tracer.currentSpan()); + log.debug("Will finish the current span after message handled " + + this.tracer.currentSpan()); } finishSpan(ex); } @@ -340,4 +362,5 @@ public final class TracingChannelInterceptor extends ChannelInterceptorAdapter private boolean emptyMessage(Message message) { return message == null; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TracingConnectionFactoryBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TracingConnectionFactoryBeanPostProcessor.java index 5d056df62..b2b117eac 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TracingConnectionFactoryBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TracingConnectionFactoryBeanPostProcessor.java @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.instrument.messaging; import java.lang.reflect.Field; + import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSContext; @@ -48,6 +49,7 @@ import org.springframework.lang.Nullable; /** * {@link BeanPostProcessor} wrapping around JMS {@link ConnectionFactory} + * * @author Adrian Cole * @since 2.1.0 */ @@ -59,10 +61,13 @@ class TracingConnectionFactoryBeanPostProcessor implements BeanPostProcessor { this.beanFactory = beanFactory; } - @Override public Object postProcessAfterInitialization(Object bean, String beanName) + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - // Wrap the caching connection factories instead of its target, because it catches callbacks - // such as ExceptionListener. If we don't wrap, cached callbacks like this won't be traced. + // Wrap the caching connection factories instead of its target, because it catches + // callbacks + // such as ExceptionListener. If we don't wrap, cached callbacks like this won't + // be traced. if (bean instanceof CachingConnectionFactory) { return new LazyConnectionFactory(this.beanFactory, (CachingConnectionFactory) bean); @@ -76,7 +81,8 @@ class TracingConnectionFactoryBeanPostProcessor implements BeanPostProcessor { } return bean; } - // We check XA first in case the ConnectionFactory also implements XAConnectionFactory + // We check XA first in case the ConnectionFactory also implements + // XAConnectionFactory if (bean instanceof XAConnectionFactory) { return new LazyXAConnectionFactory(this.beanFactory, (XAConnectionFactory) bean); @@ -86,13 +92,17 @@ class TracingConnectionFactoryBeanPostProcessor implements BeanPostProcessor { } return bean; } + } class LazyXAConnectionFactory implements XAConnectionFactory { private final BeanFactory beanFactory; + private final XAConnectionFactory delegate; + private JmsTracing jmsTracing; + private XAConnectionFactory wrappedDelegate; LazyXAConnectionFactory(BeanFactory beanFactory, XAConnectionFactory delegate) { @@ -100,20 +110,23 @@ class LazyXAConnectionFactory implements XAConnectionFactory { this.delegate = delegate; } - @Override public XAConnection createXAConnection() throws JMSException { + @Override + public XAConnection createXAConnection() throws JMSException { return wrappedDelegate().createXAConnection(); } - @Override public XAConnection createXAConnection(String s, String s1) - throws JMSException { + @Override + public XAConnection createXAConnection(String s, String s1) throws JMSException { return wrappedDelegate().createXAConnection(s, s1); } - @Override public XAJMSContext createXAContext() { + @Override + public XAJMSContext createXAContext() { return wrappedDelegate().createXAContext(); } - @Override public XAJMSContext createXAContext(String s, String s1) { + @Override + public XAJMSContext createXAContext(String s, String s1) { return wrappedDelegate().createXAContext(s, s1); } @@ -130,13 +143,17 @@ class LazyXAConnectionFactory implements XAConnectionFactory { } return this.wrappedDelegate = jmsTracing().xaConnectionFactory(this.delegate); } + } class LazyConnectionFactory implements ConnectionFactory { private final BeanFactory beanFactory; + private final ConnectionFactory delegate; + private JmsTracing jmsTracing; + private ConnectionFactory wrappedDelegate; LazyConnectionFactory(BeanFactory beanFactory, ConnectionFactory delegate) { @@ -144,28 +161,33 @@ class LazyConnectionFactory implements ConnectionFactory { this.delegate = delegate; } - @Override public Connection createConnection() throws JMSException { + @Override + public Connection createConnection() throws JMSException { return wrappedDelegate().createConnection(); } - @Override public Connection createConnection(String s, String s1) - throws JMSException { + @Override + public Connection createConnection(String s, String s1) throws JMSException { return wrappedDelegate().createConnection(s, s1); } - @Override public JMSContext createContext() { + @Override + public JMSContext createContext() { return wrappedDelegate().createContext(); } - @Override public JMSContext createContext(String s, String s1) { + @Override + public JMSContext createContext(String s, String s1) { return wrappedDelegate().createContext(s, s1); } - @Override public JMSContext createContext(String s, String s1, int i) { + @Override + public JMSContext createContext(String s, String s1, int i) { return wrappedDelegate().createContext(s, s1, i); } - @Override public JMSContext createContext(int i) { + @Override + public JMSContext createContext(int i) { return wrappedDelegate().createContext(i); } @@ -182,12 +204,15 @@ class LazyConnectionFactory implements ConnectionFactory { } return this.wrappedDelegate = jmsTracing().connectionFactory(this.delegate); } + } class LazyMessageListener implements MessageListener { private final BeanFactory beanFactory; + private final MessageListener delegate; + private JmsTracing jmsTracing; LazyMessageListener(BeanFactory beanFactory, MessageListener delegate) { @@ -195,7 +220,8 @@ class LazyMessageListener implements MessageListener { this.delegate = delegate; } - @Override public void onMessage(Message message) { + @Override + public void onMessage(Message message) { wrappedDelegate().onMessage(message); } @@ -207,19 +233,26 @@ class LazyMessageListener implements MessageListener { } private MessageListener wrappedDelegate() { - // Adds a consumer span as we have no visibility into JCA's implementation of messaging + // Adds a consumer span as we have no visibility into JCA's implementation of + // messaging return jmsTracing().messageListener(this.delegate, true); } + } /** - * This ensures listeners end up continuing the trace from {@link MessageConsumer#receive()} + * This ensures listeners end up continuing the trace from + * {@link MessageConsumer#receive()} */ class TracingJmsListenerEndpointRegistry extends JmsListenerEndpointRegistry { + final JmsTracing jmsTracing; + final CurrentTraceContext current; + // Not all state can be copied without using reflection final Field messageHandlerMethodFactoryField; + final Field embeddedValueResolverField; TracingJmsListenerEndpointRegistry(JmsTracing jmsTracing, @@ -230,7 +263,25 @@ class TracingJmsListenerEndpointRegistry extends JmsListenerEndpointRegistry { this.embeddedValueResolverField = tryField("embeddedValueResolver"); } - @Override public void registerListenerContainer(JmsListenerEndpoint endpoint, + @Nullable + static Field tryField(String name) { + try { + Field field = MethodJmsListenerEndpoint.class.getDeclaredField(name); + field.setAccessible(true); + return field; + } + catch (NoSuchFieldException e) { + return null; + } + } + + @Nullable + static T get(Object object, Field field) throws IllegalAccessException { + return (T) field.get(object); + } + + @Override + public void registerListenerContainer(JmsListenerEndpoint endpoint, JmsListenerContainerFactory factory, boolean startImmediately) { if (endpoint instanceof MethodJmsListenerEndpoint) { endpoint = trace((MethodJmsListenerEndpoint) endpoint); @@ -242,7 +293,8 @@ class TracingJmsListenerEndpointRegistry extends JmsListenerEndpointRegistry { } /** - * This wraps the {@link SimpleJmsListenerEndpoint#getMessageListener()} delegate in a new span. + * This wraps the {@link SimpleJmsListenerEndpoint#getMessageListener()} delegate in a + * new span. */ SimpleJmsListenerEndpoint trace(SimpleJmsListenerEndpoint source) { MessageListener delegate = source.getMessageListener(); @@ -253,14 +305,16 @@ class TracingJmsListenerEndpointRegistry extends JmsListenerEndpointRegistry { } /** - * It would be better to trace by wrapping, but {@link MethodJmsListenerEndpoint#createMessageListener(MessageListenerContainer)}, - * is protected so we can't call it from outside code. In other words, a forwarding pattern can't - * be used. Instead, we copy state from the input. + * It would be better to trace by wrapping, but + * {@link MethodJmsListenerEndpoint#createMessageListener(MessageListenerContainer)}, + * is protected so we can't call it from outside code. In other words, a forwarding + * pattern can't be used. Instead, we copy state from the input. *

    - * NOTE: As {@linkplain MethodJmsListenerEndpoint} is neither final, nor effectively final. For - * this reason we can't ensure copying will get all state. For example, a subtype could hold state - * we aren't aware of, or change behavior. We can consider checking that input is not a subtype, - * and most conservatively leaving unknown subtypes untraced. + * NOTE: As {@linkplain MethodJmsListenerEndpoint} is neither final, nor effectively + * final. For this reason we can't ensure copying will get all state. For example, a + * subtype could hold state we aren't aware of, or change behavior. We can consider + * checking that input is not a subtype, and most conservatively leaving unknown + * subtypes untraced. */ MethodJmsListenerEndpoint trace(MethodJmsListenerEndpoint source) { // Skip out rather than incompletely copying the source @@ -269,9 +323,11 @@ class TracingJmsListenerEndpointRegistry extends JmsListenerEndpointRegistry { return source; } - // We want the stock implementation, except we want to wrap the message listener in a new span + // We want the stock implementation, except we want to wrap the message listener + // in a new span MethodJmsListenerEndpoint dest = new MethodJmsListenerEndpoint() { - @Override protected MessagingMessageListenerAdapter createMessageListenerInstance() { + @Override + protected MessagingMessageListenerAdapter createMessageListenerInstance() { return new TracingMessagingMessageListenerAdapter( TracingJmsListenerEndpointRegistry.this.jmsTracing, TracingJmsListenerEndpointRegistry.this.current); @@ -301,20 +357,6 @@ class TracingJmsListenerEndpointRegistry extends JmsListenerEndpointRegistry { return dest; } - @Nullable static Field tryField(String name) { - try { - Field field = MethodJmsListenerEndpoint.class.getDeclaredField(name); - field.setAccessible(true); - return field; - } - catch (NoSuchFieldException e) { - return null; - } - } - - @Nullable static T get(Object object, Field field) throws IllegalAccessException { - return (T) field.get(object); - } } /** @@ -324,6 +366,7 @@ final class TracingMessagingMessageListenerAdapter extends MessagingMessageListenerAdapter { final JmsTracing jmsTracing; + final CurrentTraceContext current; TracingMessagingMessageListenerAdapter(JmsTracing jmsTracing, @@ -332,8 +375,8 @@ final class TracingMessagingMessageListenerAdapter this.current = current; } - @Override public void onMessage(Message message, Session session) - throws JMSException { + @Override + public void onMessage(Message message, Session session) throws JMSException { Span span = this.jmsTracing.nextSpan(message).name("on-message").start(); try (CurrentTraceContext.Scope ws = this.current.newScope(span.context())) { super.onMessage(message, session); @@ -346,4 +389,5 @@ final class TracingMessagingMessageListenerAdapter span.finish(); } } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/websocket/TraceWebSocketAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/websocket/TraceWebSocketAutoConfiguration.java index f9a2894e9..076f9b9f4 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/websocket/TraceWebSocketAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/websocket/TraceWebSocketAutoConfiguration.java @@ -35,7 +35,6 @@ import org.springframework.web.socket.config.annotation.StompEndpointRegistry; * * @author Dave Syer * @since 1.0.0 - * * @see AbstractWebSocketMessageBrokerConfigurer */ @Configuration @@ -55,7 +54,8 @@ public class TraceWebSocketAutoConfiguration @Override public void configureMessageBroker(MessageBrokerRegistry registry) { - registry.configureBrokerChannel().setInterceptors(TracingChannelInterceptor.create(this.tracing)); + registry.configureBrokerChannel() + .setInterceptors(TracingChannelInterceptor.create(this.tracing)); } @Override @@ -67,4 +67,5 @@ public class TraceWebSocketAutoConfiguration public void configureClientInboundChannel(ChannelRegistration registration) { registration.setInterceptors(TracingChannelInterceptor.create(this.tracing)); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/opentracing/OpentracingAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/opentracing/OpentracingAutoConfiguration.java index 25dba6e2b..5961db938 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/opentracing/OpentracingAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/opentracing/OpentracingAutoConfiguration.java @@ -28,15 +28,15 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * to enable tracing via Opentracing. + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} to enable tracing via Opentracing. * * @author Spencer Gibb * @author Marcin Grzejszczak * @since 2.0.0 */ @Configuration -@ConditionalOnProperty(value="spring.sleuth.opentracing.enabled", matchIfMissing=true) +@ConditionalOnProperty(value = "spring.sleuth.opentracing.enabled", matchIfMissing = true) @ConditionalOnBean(Tracing.class) @ConditionalOnClass(Tracer.class) @EnableConfigurationProperties(SleuthOpentracingProperties.class) @@ -48,4 +48,5 @@ public class OpentracingAutoConfiguration { Tracer sleuthOpenTracing(brave.Tracing braveTracing) { return BraveTracer.create(braveTracing); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/opentracing/SleuthOpentracingProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/opentracing/SleuthOpentracingProperties.java index a8c874d8b..c4d157944 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/opentracing/SleuthOpentracingProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/opentracing/SleuthOpentracingProperties.java @@ -19,8 +19,9 @@ package org.springframework.cloud.sleuth.instrument.opentracing; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Sleuth Opentracing settings + * Sleuth Opentracing settings. * + * @author Marcin Grzejszczak * @since 2.0.0 */ @ConfigurationProperties("spring.sleuth.opentracing") diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/LazySpanSubscriber.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/LazySpanSubscriber.java index ae58a933f..5b41e885b 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/LazySpanSubscriber.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/LazySpanSubscriber.java @@ -23,8 +23,9 @@ import org.reactivestreams.Subscription; import reactor.util.context.Context; /** - * A lazy representation of the {@link SpanSubscription} + * A lazy representation of the {@link SpanSubscription}. * + * @param - type of what subscription returns * @author Marcin Grzejszczak * @since 2.0.0 */ @@ -36,32 +37,39 @@ final class LazySpanSubscriber extends AtomicBoolean implements SpanSubscript this.supplier = supplier; } - @Override public void onSubscribe(Subscription subscription) { + @Override + public void onSubscribe(Subscription subscription) { this.supplier.get().onSubscribe(subscription); } - @Override public void request(long n) { + @Override + public void request(long n) { this.supplier.get().request(n); } - @Override public void cancel() { + @Override + public void cancel() { this.supplier.get().cancel(); } - @Override public void onNext(T o) { + @Override + public void onNext(T o) { this.supplier.get().onNext(o); } - @Override public void onError(Throwable throwable) { + @Override + public void onError(Throwable throwable) { this.supplier.get().onError(throwable); } - @Override public void onComplete() { + @Override + public void onComplete() { this.supplier.get().onComplete(); } - @Override public Context currentContext() { + @Override + public Context currentContext() { return this.supplier.get().currentContext(); } -} +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorSleuth.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorSleuth.java index 46dd82dfd..af6489705 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorSleuth.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ReactorSleuth.java @@ -16,6 +16,8 @@ package org.springframework.cloud.sleuth.instrument.reactor; +import java.util.function.Function; + import brave.Tracing; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -29,10 +31,8 @@ import reactor.core.publisher.GroupedFlux; import reactor.core.publisher.Operators; import reactor.util.context.Context; -import java.util.function.Function; - /** - * Reactive Span pointcuts factories + * Reactive Span pointcuts factories. * * @author Stephane Maldini * @since 2.0.0 @@ -41,17 +41,18 @@ public abstract class ReactorSleuth { private static final Log log = LogFactory.getLog(ReactorSleuth.class); + private ReactorSleuth() { + } + /** - * Return a span operator pointcut given a {@link BeanFactory}. This can be used in reactor - * via {@link reactor.core.publisher.Flux#transform(Function)}, {@link - * reactor.core.publisher.Mono#transform(Function)}, {@link - * reactor.core.publisher.Hooks#onEachOperator(Function)} or {@link - * reactor.core.publisher.Hooks#onLastOperator(Function)}. - * + * Return a span operator pointcut given a {@link BeanFactory}. This can be used in + * reactor via {@link reactor.core.publisher.Flux#transform(Function)}, + * {@link reactor.core.publisher.Mono#transform(Function)}, + * {@link reactor.core.publisher.Hooks#onEachOperator(Function)} or + * {@link reactor.core.publisher.Hooks#onLastOperator(Function)}. * @deprecated use {@link ReactorSleuth#scopePassingSpanOperator} instead - * @param beanFactory + * @param beanFactory - {@link BeanFactory} * @param an arbitrary type that is left unchanged by the span operator - * * @return a new lazy span operator pointcut */ @SuppressWarnings("unchecked") @@ -59,119 +60,127 @@ public abstract class ReactorSleuth { public static Function, ? extends Publisher> spanOperator( BeanFactory beanFactory) { - if(log.isWarnEnabled()){ - log.warn("spanOperator method will be deleted in the next major release. " + - "Use scopePassingSpanOperator() method instead"); + if (log.isWarnEnabled()) { + log.warn("spanOperator method will be deleted in the next major release. " + + "Use scopePassingSpanOperator() method instead"); } - return sourcePub -> { + return (sourcePub -> { // TODO: Remove this once Reactor 3.1.8 is released - //do the checks directly on actual original Publisher - if (sourcePub instanceof ConnectableFlux //Operators.lift can't handle that - || sourcePub instanceof GroupedFlux //Operators.lift can't handle that - ) { + // do the checks directly on actual original Publisher + if (sourcePub instanceof ConnectableFlux // Operators.lift can't handle that + || sourcePub instanceof GroupedFlux // Operators.lift can't handle + // that + ) { return sourcePub; } - //no more POINTCUT_FILTER since mechanism is broken - Function, ? extends Publisher> lift = Operators.lift((scannable, sub) -> { - if (contextRefreshed(beanFactory)) { - if (log.isTraceEnabled()) { - log.trace("Spring Context already refreshed. Creating a Sleuth span subscriber with Reactor Context " + "[" + sub.currentContext() + "] and name [" + scannable.name() + "]"); - } - return spanSubscriptionProvider(beanFactory, scannable, sub).get(); - } - if (log.isTraceEnabled()) { - log.trace( - "Spring Context is not yet refreshed, falling back to lazy span subscriber. Reactor Context is [" + sub.currentContext() + "] and name is [" + scannable.name() + "]"); - } - //rest of the logic unchanged... - return new LazySpanSubscriber( - spanSubscriptionProvider(beanFactory, scannable, sub) - ); - }); + // no more POINTCUT_FILTER since mechanism is broken + Function, ? extends Publisher> lift = Operators + .lift((scannable, sub) -> { + if (contextRefreshed(beanFactory)) { + if (log.isTraceEnabled()) { + log.trace( + "Spring Context already refreshed. Creating a Sleuth span subscriber with Reactor Context " + + "[" + sub.currentContext() + + "] and name [" + scannable.name() + + "]"); + } + return spanSubscriptionProvider(beanFactory, scannable, sub) + .get(); + } + if (log.isTraceEnabled()) { + log.trace( + "Spring Context is not yet refreshed, falling back to lazy span subscriber. Reactor Context is [" + + sub.currentContext() + "] and name is [" + + scannable.name() + "]"); + } + // rest of the logic unchanged... + return new LazySpanSubscriber( + spanSubscriptionProvider(beanFactory, scannable, sub)); + }); return lift.apply(sourcePub); - }; + }); } private static SpanSubscriptionProvider spanSubscriptionProvider( BeanFactory beanFactory, Scannable scannable, CoreSubscriber sub) { - return new SpanSubscriptionProvider( - beanFactory, - sub, - sub.currentContext(), + return new SpanSubscriptionProvider(beanFactory, sub, sub.currentContext(), scannable.name()); } /** - * Return a span operator pointcut given a {@link Tracing}. This can be used in reactor - * via {@link reactor.core.publisher.Flux#transform(Function)}, {@link - * reactor.core.publisher.Mono#transform(Function)}, {@link - * reactor.core.publisher.Hooks#onEachOperator(Function)} or {@link - * reactor.core.publisher.Hooks#onLastOperator(Function)}. The Span operator + * Return a span operator pointcut given a {@link Tracing}. This can be used in + * reactor via {@link reactor.core.publisher.Flux#transform(Function)}, + * {@link reactor.core.publisher.Mono#transform(Function)}, + * {@link reactor.core.publisher.Hooks#onEachOperator(Function)} or + * {@link reactor.core.publisher.Hooks#onLastOperator(Function)}. The Span operator * pointcut will pass the Scope of the Span without ever creating any new spans. - * - * @param beanFactory + * @param beanFactory - {@link BeanFactory} * @param an arbitrary type that is left unchanged by the span operator - * * @return a new lazy span operator pointcut */ @SuppressWarnings("unchecked") public static Function, ? extends Publisher> scopePassingSpanOperator( BeanFactory beanFactory) { - return sourcePub -> { + return (sourcePub -> { // TODO: Remove this once Reactor 3.1.8 is released - //do the checks directly on actual original Publisher - if (sourcePub instanceof ConnectableFlux //Operators.lift can't handle that - || sourcePub instanceof GroupedFlux //Operators.lift can't handle that - ) { + // do the checks directly on actual original Publisher + if (sourcePub instanceof ConnectableFlux // Operators.lift can't handle that + || sourcePub instanceof GroupedFlux // Operators.lift can't handle + // that + ) { return sourcePub; } - //no more POINTCUT_FILTER since mechanism is broken - Function, ? extends Publisher> lift = Operators.lift((scannable, sub) -> { - //rest of the logic unchanged... - if (contextRefreshed(beanFactory)) { - if (log.isTraceEnabled()) { - log.trace("Spring Context already refreshed. Creating a scope " + "passing span subscriber with Reactor Context " + "[" + sub.currentContext() + "] and name [" + scannable.name() + "]"); - } - return scopePassingSpanSubscription(beanFactory, scannable, sub).get(); - } - if (log.isTraceEnabled()) { - log.trace( - "Spring Context is not yet refreshed, falling back to lazy span subscriber. Reactor Context is [" + sub.currentContext() + "] and name is [" + scannable.name() + "]"); - } - return new LazySpanSubscriber( - scopePassingSpanSubscription(beanFactory, scannable, sub) - ); - }); + // no more POINTCUT_FILTER since mechanism is broken + Function, ? extends Publisher> lift = Operators + .lift((scannable, sub) -> { + // rest of the logic unchanged... + if (contextRefreshed(beanFactory)) { + if (log.isTraceEnabled()) { + log.trace( + "Spring Context already refreshed. Creating a scope " + + "passing span subscriber with Reactor Context " + + "[" + sub.currentContext() + + "] and name [" + scannable.name() + + "]"); + } + return scopePassingSpanSubscription(beanFactory, scannable, + sub).get(); + } + if (log.isTraceEnabled()) { + log.trace( + "Spring Context is not yet refreshed, falling back to lazy span subscriber. Reactor Context is [" + + sub.currentContext() + "] and name is [" + + scannable.name() + "]"); + } + return new LazySpanSubscriber(scopePassingSpanSubscription( + beanFactory, scannable, sub)); + }); return lift.apply(sourcePub); - }; + }); } private static boolean contextRefreshed(BeanFactory beanFactory) { try { - return beanFactory.getBean(ApplicationContextRefreshedListener.class).isRefreshed(); - } catch (NoSuchBeanDefinitionException e) { + return beanFactory.getBean(ApplicationContextRefreshedListener.class) + .isRefreshed(); + } + catch (NoSuchBeanDefinitionException ex) { return false; } } private static SpanSubscriptionProvider scopePassingSpanSubscription( BeanFactory beanFactory, Scannable scannable, CoreSubscriber sub) { - return new SpanSubscriptionProvider( - beanFactory, - sub, - sub.currentContext(), + return new SpanSubscriptionProvider(beanFactory, sub, sub.currentContext(), scannable.name()) { - @Override SpanSubscription newCoreSubscriber(Tracing tracing) { - return new ScopePassingSpanSubscriber( - sub, - sub != null ? sub.currentContext() : Context.empty(), - tracing); + @Override + SpanSubscription newCoreSubscriber(Tracing tracing) { + return new ScopePassingSpanSubscriber(sub, + sub != null ? sub.currentContext() : Context.empty(), tracing); } }; } - private ReactorSleuth() { - } -} \ No newline at end of file +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ScopePassingSpanSubscriber.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ScopePassingSpanSubscriber.java index 741432d71..906aef757 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ScopePassingSpanSubscriber.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/ScopePassingSpanSubscriber.java @@ -21,81 +21,94 @@ import java.util.concurrent.atomic.AtomicBoolean; import brave.Span; import brave.Tracer; import brave.Tracing; -import reactor.util.context.Context; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; +import reactor.util.context.Context; /** - * A trace representation of the {@link Subscriber} that always - * continues a span + * A trace representation of the {@link Subscriber} that always continues a span. * + * @param - span subscription type * @author Marcin Grzejszczak * @since 2.0.0 */ -final class ScopePassingSpanSubscriber extends AtomicBoolean implements SpanSubscription { +final class ScopePassingSpanSubscriber extends AtomicBoolean + implements SpanSubscription { private static final Log log = LogFactory.getLog(ScopePassingSpanSubscriber.class); private final Span span; + private final Subscriber subscriber; + private final Context context; + private final Tracer tracer; + private Subscription s; - ScopePassingSpanSubscriber(Subscriber subscriber, Context ctx, Tracing tracing) { + ScopePassingSpanSubscriber(Subscriber subscriber, Context ctx, + Tracing tracing) { this.subscriber = subscriber; this.tracer = tracing.tracer(); - Span root = ctx != null ? - ctx.getOrDefault(Span.class, this.tracer.currentSpan()) : null; + Span root = ctx != null ? ctx.getOrDefault(Span.class, this.tracer.currentSpan()) + : null; this.span = root; - this.context = ctx != null && root != null ? ctx.put(Span.class, root) : - ctx != null ? ctx : Context.empty(); + this.context = ctx != null && root != null ? ctx.put(Span.class, root) + : ctx != null ? ctx : Context.empty(); if (log.isTraceEnabled()) { log.trace("Root span [" + root + "], context [" + this.context + "]"); } } - @Override public void onSubscribe(Subscription subscription) { + @Override + public void onSubscribe(Subscription subscription) { this.s = subscription; try (Tracer.SpanInScope inScope = this.tracer.withSpanInScope(this.span)) { this.subscriber.onSubscribe(this); } } - @Override public void request(long n) { + @Override + public void request(long n) { try (Tracer.SpanInScope inScope = this.tracer.withSpanInScope(this.span)) { this.s.request(n); } } - @Override public void cancel() { + @Override + public void cancel() { try (Tracer.SpanInScope inScope = this.tracer.withSpanInScope(this.span)) { this.s.cancel(); } } - @Override public void onNext(T o) { + @Override + public void onNext(T o) { try (Tracer.SpanInScope inScope = this.tracer.withSpanInScope(this.span)) { this.subscriber.onNext(o); } } - @Override public void onError(Throwable throwable) { + @Override + public void onError(Throwable throwable) { try (Tracer.SpanInScope inScope = this.tracer.withSpanInScope(this.span)) { this.subscriber.onError(throwable); } } - @Override public void onComplete() { + @Override + public void onComplete() { try (Tracer.SpanInScope inScope = this.tracer.withSpanInScope(this.span)) { this.subscriber.onComplete(); } } - @Override public Context currentContext() { + @Override + public Context currentContext() { return this.context; } -} \ No newline at end of file +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SleuthReactorProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SleuthReactorProperties.java index 0ec47e8ca..20b3ac634 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SleuthReactorProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SleuthReactorProperties.java @@ -19,15 +19,16 @@ package org.springframework.cloud.sleuth.instrument.reactor; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Sleuth Reactor settings + * Sleuth Reactor settings. * + * @author Marcin Grzejszczak * @since 2.0.2 */ @ConfigurationProperties("spring.sleuth.reactor.enabled") public class SleuthReactorProperties { /** - * When true enables instrumentation for reactor + * When true enables instrumentation for reactor. */ private boolean enabled = true; @@ -38,4 +39,5 @@ public class SleuthReactorProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriber.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriber.java index cd3a5a445..8bad7e2dd 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriber.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriber.java @@ -16,6 +16,8 @@ package org.springframework.cloud.sleuth.instrument.reactor; +import java.util.concurrent.atomic.AtomicBoolean; + import brave.Span; import brave.Tracer; import brave.Tracing; @@ -26,12 +28,11 @@ import reactor.util.Logger; import reactor.util.Loggers; import reactor.util.context.Context; -import java.util.concurrent.atomic.AtomicBoolean; - /** - * A trace representation of the {@link Subscriber} + * A trace representation of the {@link Subscriber}. * * @deprecated use {@link ScopePassingSpanSubscriber} instead + * @param - return type of the subscriber * @author Stephane Maldini * @author Marcin Grzejszczak * @since 2.0.0 @@ -39,14 +40,18 @@ import java.util.concurrent.atomic.AtomicBoolean; @Deprecated final class SpanSubscriber extends AtomicBoolean implements SpanSubscription { - private static final Logger log = Loggers.getLogger( - SpanSubscriber.class); + private static final Logger log = Loggers.getLogger(SpanSubscriber.class); private final Span span; + private final Span rootSpan; + private final Subscriber subscriber; + private final Context context; + private final Tracer tracer; + private Subscription s; SpanSubscriber(Subscriber subscriber, Context ctx, Tracing tracing, @@ -61,16 +66,17 @@ final class SpanSubscriber extends AtomicBoolean implements SpanSubscription< if (log.isTraceEnabled()) { log.trace("Stored context root span [{}]", this.rootSpan); } - this.span = root != null ? - this.tracer.nextSpan(TraceContextOrSamplingFlags.create(root.context())) - .name(name) : this.tracer.nextSpan().name(name); + this.span = root != null ? this.tracer + .nextSpan(TraceContextOrSamplingFlags.create(root.context())).name(name) + : this.tracer.nextSpan().name(name); if (log.isTraceEnabled()) { log.trace("Created span [{}], with name [{}]", this.span, name); } this.context = ctx.put(Span.class, this.span); } - @Override public void onSubscribe(Subscription subscription) { + @Override + public void onSubscribe(Subscription subscription) { if (log.isTraceEnabled()) { log.trace("On subscribe"); } @@ -83,7 +89,8 @@ final class SpanSubscriber extends AtomicBoolean implements SpanSubscription< } } - @Override public void request(long n) { + @Override + public void request(long n) { if (log.isTraceEnabled()) { log.trace("Request"); } @@ -100,7 +107,8 @@ final class SpanSubscriber extends AtomicBoolean implements SpanSubscription< } } - @Override public void cancel() { + @Override + public void cancel() { try { if (log.isTraceEnabled()) { log.trace("Cancel"); @@ -112,11 +120,13 @@ final class SpanSubscriber extends AtomicBoolean implements SpanSubscription< } } - @Override public void onNext(T o) { + @Override + public void onNext(T o) { this.subscriber.onNext(o); } - @Override public void onError(Throwable throwable) { + @Override + public void onError(Throwable throwable) { try { this.subscriber.onError(throwable); } @@ -125,7 +135,8 @@ final class SpanSubscriber extends AtomicBoolean implements SpanSubscription< } } - @Override public void onComplete() { + @Override + public void onComplete() { try { this.subscriber.onComplete(); } @@ -152,7 +163,9 @@ final class SpanSubscriber extends AtomicBoolean implements SpanSubscription< } } - @Override public Context currentContext() { + @Override + public Context currentContext() { return this.context; } -} \ No newline at end of file + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscription.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscription.java index d62183daa..ce412d26e 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscription.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscription.java @@ -22,12 +22,14 @@ import reactor.core.Fuseable; /** * A {@link SpanSubscription} is a {@link Subscription} that fakes being {@link Fuseable} - * (implementing {@link reactor.core.Fuseable.QueueSubscription} with default no-op methods - * and always negotiating fusion to be {@link Fuseable#NONE}). + * (implementing {@link reactor.core.Fuseable.QueueSubscription} with default no-op + * methods and always negotiating fusion to be {@link Fuseable#NONE}). * * @author Marcin Grzejszczak + * @param - type of the subsciption */ -interface SpanSubscription extends Subscription, CoreSubscriber, Fuseable.QueueSubscription { +interface SpanSubscription + extends Subscription, CoreSubscriber, Fuseable.QueueSubscription { @Override default T poll() { @@ -36,7 +38,7 @@ interface SpanSubscription extends Subscription, CoreSubscriber, Fuseable. @Override default int requestFusion(int i) { - return Fuseable.NONE; //always negotiate to no fusion + return Fuseable.NONE; // always negotiate to no fusion } @Override @@ -51,7 +53,7 @@ interface SpanSubscription extends Subscription, CoreSubscriber, Fuseable. @Override default void clear() { - //NO-OP + // NO-OP } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriptionProvider.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriptionProvider.java index 3fa591754..8705e7c0b 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriptionProvider.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriptionProvider.java @@ -19,15 +19,16 @@ package org.springframework.cloud.sleuth.instrument.reactor; import java.util.function.Supplier; import brave.Tracing; -import reactor.util.context.Context; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.reactivestreams.Subscriber; import org.springframework.beans.factory.BeanFactory; +import reactor.util.context.Context; /** - * Supplier to lazily start a {@link SpanSubscription} + * Supplier to lazily start a {@link SpanSubscription}. * + * @param type of returned subscription * @author Marcin Grzejszczak */ class SpanSubscriptionProvider implements Supplier> { @@ -35,13 +36,16 @@ class SpanSubscriptionProvider implements Supplier> { private static final Log log = LogFactory.getLog(SpanSubscriptionProvider.class); final BeanFactory beanFactory; + final Subscriber subscriber; + final Context context; + final String name; + private volatile Tracing tracing; - SpanSubscriptionProvider(BeanFactory beanFactory, - Subscriber subscriber, + SpanSubscriptionProvider(BeanFactory beanFactory, Subscriber subscriber, Context context, String name) { this.beanFactory = beanFactory; this.subscriber = subscriber; @@ -52,7 +56,8 @@ class SpanSubscriptionProvider implements Supplier> { } } - @Override public SpanSubscription get() { + @Override + public SpanSubscription get() { return newCoreSubscriber(tracing()); } @@ -66,4 +71,5 @@ class SpanSubscriptionProvider implements Supplier> { } return this.tracing; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/TraceReactorAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/TraceReactorAutoConfiguration.java index 3592ca8d5..fa58837be 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/TraceReactorAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/reactor/TraceReactorAutoConfiguration.java @@ -19,6 +19,7 @@ package org.springframework.cloud.sleuth.instrument.reactor; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; + import javax.annotation.PreDestroy; import brave.Tracing; @@ -43,15 +44,15 @@ import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * to enable tracing of Reactor components via Spring Cloud Sleuth. + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} to enable tracing of Reactor components via Spring Cloud Sleuth. * * @author Stephane Maldini * @author Marcin Grzejszczak * @since 2.0.0 */ @Configuration -@ConditionalOnProperty(value="spring.sleuth.reactor.enabled", matchIfMissing=true) +@ConditionalOnProperty(value = "spring.sleuth.reactor.enabled", matchIfMissing = true) @ConditionalOnClass(Mono.class) @AutoConfigureAfter(TraceWebFluxAutoConfiguration.class) public class TraceReactorAutoConfiguration { @@ -60,13 +61,8 @@ public class TraceReactorAutoConfiguration { @ConditionalOnBean(Tracing.class) static class TraceReactorConfiguration { - static final String SLEUTH_TRACE_REACTOR_KEY = TraceReactorConfiguration.class.getName(); - - @PreDestroy - public void cleanupHooks() { - Hooks.resetOnEachOperator(SLEUTH_TRACE_REACTOR_KEY); - Schedulers.resetFactory(); - } + static final String SLEUTH_TRACE_REACTOR_KEY = TraceReactorConfiguration.class + .getName(); @Bean // for tests @@ -75,21 +71,32 @@ public class TraceReactorAutoConfiguration { return new HookRegisteringBeanDefinitionRegistryPostProcessor(); } - @Bean ApplicationContextRefreshedListener traceApplicationContextRefreshedListener() { + @PreDestroy + public void cleanupHooks() { + Hooks.resetOnEachOperator(SLEUTH_TRACE_REACTOR_KEY); + Schedulers.resetFactory(); + } + + @Bean + ApplicationContextRefreshedListener traceApplicationContextRefreshedListener() { return new ApplicationContextRefreshedListener(); } + } + } -class HookRegisteringBeanDefinitionRegistryPostProcessor implements - BeanDefinitionRegistryPostProcessor { +class HookRegisteringBeanDefinitionRegistryPostProcessor + implements BeanDefinitionRegistryPostProcessor { - @Override public void postProcessBeanDefinitionRegistry( - BeanDefinitionRegistry registry) throws BeansException { + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) + throws BeansException { } - @Override public void postProcessBeanFactory( - ConfigurableListableBeanFactory beanFactory) throws BeansException { + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) + throws BeansException { setupHooks(beanFactory); } @@ -102,17 +109,18 @@ class HookRegisteringBeanDefinitionRegistryPostProcessor implements private Schedulers.Factory factoryInstance(final BeanFactory beanFactory) { return new Schedulers.Factory() { - @Override public ScheduledExecutorService decorateExecutorService(String schedulerType, + @Override + public ScheduledExecutorService decorateExecutorService(String schedulerType, Supplier actual) { - return new TraceableScheduledExecutorService(beanFactory, - actual.get()); + return new TraceableScheduledExecutorService(beanFactory, actual.get()); } }; } + } -class ApplicationContextRefreshedListener implements - ApplicationListener { +class ApplicationContextRefreshedListener + implements ApplicationListener { AtomicBoolean refreshed = new AtomicBoolean(); @@ -124,4 +132,5 @@ class ApplicationContextRefreshedListener implements boolean isRefreshed() { return this.refreshed.get(); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/RxJavaAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/RxJavaAutoConfiguration.java index 9d3d6fb42..e95016566 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/RxJavaAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/RxJavaAutoConfiguration.java @@ -31,8 +31,8 @@ import org.springframework.context.annotation.Configuration; import rx.plugins.RxJavaSchedulersHook; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} that - * enables support for RxJava via {@link RxJavaSchedulersHook}. + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} that enables support for RxJava via {@link RxJavaSchedulersHook}. * * @author Shivang Shah * @since 1.0.0 @@ -51,4 +51,5 @@ public class RxJavaAutoConfiguration { return new SleuthRxJavaSchedulersHook(tracer, Arrays.asList(sleuthRxJavaSchedulersProperties.getIgnoredthreads())); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHook.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHook.java index 57089deba..24a96874d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHook.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHook.java @@ -37,12 +37,14 @@ import rx.plugins.RxJavaSchedulersHook; */ class SleuthRxJavaSchedulersHook extends RxJavaSchedulersHook { - private static final Log log = LogFactory.getLog( - SleuthRxJavaSchedulersHook.class); + private static final Log log = LogFactory.getLog(SleuthRxJavaSchedulersHook.class); private static final String RXJAVA_COMPONENT = "rxjava"; + private final Tracer tracer; + private final List threadsToSample; + private RxJavaSchedulersHook delegate; SleuthRxJavaSchedulersHook(Tracer tracer, List threadsToSample) { @@ -53,27 +55,28 @@ class SleuthRxJavaSchedulersHook extends RxJavaSchedulersHook { if (this.delegate instanceof SleuthRxJavaSchedulersHook) { return; } - RxJavaErrorHandler errorHandler = RxJavaPlugins.getInstance().getErrorHandler(); - RxJavaObservableExecutionHook observableExecutionHook - = RxJavaPlugins.getInstance().getObservableExecutionHook(); + RxJavaErrorHandler errorHandler = RxJavaPlugins.getInstance() + .getErrorHandler(); + RxJavaObservableExecutionHook observableExecutionHook = RxJavaPlugins + .getInstance().getObservableExecutionHook(); logCurrentStateOfRxJavaPlugins(errorHandler, observableExecutionHook); RxJavaPlugins.getInstance().reset(); RxJavaPlugins.getInstance().registerSchedulersHook(this); RxJavaPlugins.getInstance().registerErrorHandler(errorHandler); - RxJavaPlugins.getInstance().registerObservableExecutionHook(observableExecutionHook); - } catch (Exception e) { - log.error("Failed to register Sleuth RxJava SchedulersHook", e); + RxJavaPlugins.getInstance() + .registerObservableExecutionHook(observableExecutionHook); + } + catch (Exception ex) { + log.error("Failed to register Sleuth RxJava SchedulersHook", ex); } } private void logCurrentStateOfRxJavaPlugins(RxJavaErrorHandler errorHandler, - RxJavaObservableExecutionHook observableExecutionHook) { + RxJavaObservableExecutionHook observableExecutionHook) { if (log.isDebugEnabled()) { - log.debug("Current RxJava plugins configuration is [" - + "schedulersHook [" + this.delegate + "]," - + "errorHandler [" + errorHandler + "]," - + "observableExecutionHook [" + observableExecutionHook + "]," - + "]"); + log.debug("Current RxJava plugins configuration is [" + "schedulersHook [" + + this.delegate + "]," + "errorHandler [" + errorHandler + "]," + + "observableExecutionHook [" + observableExecutionHook + "]," + "]"); log.debug("Registering Sleuth RxJava Schedulers Hook."); } } @@ -83,26 +86,32 @@ class SleuthRxJavaSchedulersHook extends RxJavaSchedulersHook { if (action instanceof TraceAction) { return action; } - Action0 wrappedAction = this.delegate != null - ? this.delegate.onSchedule(action) : action; + Action0 wrappedAction = this.delegate != null ? this.delegate.onSchedule(action) + : action; if (wrappedAction instanceof TraceAction) { return action; } - return super.onSchedule(new TraceAction(this.tracer, wrappedAction, - this.threadsToSample)); + return super.onSchedule( + new TraceAction(this.tracer, wrappedAction, this.threadsToSample)); } + /** + * Wrapped Action element. + * @author Marcin Grzejszczak + */ static class TraceAction implements Action0 { private static final String THREAD_NAME_KEY = "thread"; private final Action0 actual; + private final Tracer tracer; + private final Span parent; + private final List threadsToIgnore; - public TraceAction(Tracer tracer, Action0 actual, - List threadsToIgnore) { + TraceAction(Tracer tracer, Action0 actual, List threadsToIgnore) { this.tracer = tracer; this.threadsToIgnore = threadsToIgnore; this.parent = this.tracer.currentSpan(); @@ -129,18 +138,22 @@ class SleuthRxJavaSchedulersHook extends RxJavaSchedulersHook { boolean created = false; if (span != null) { span = this.tracer.toSpan(this.parent.context()); - } else { + } + else { span = this.tracer.nextSpan().name(RXJAVA_COMPONENT).start(); span.tag(THREAD_NAME_KEY, Thread.currentThread().getName()); created = true; } try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { this.actual.call(); - } finally { + } + finally { if (created) { span.finish(); } } } + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersProperties.java index e884a7aa2..a58424008 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersProperties.java @@ -19,7 +19,7 @@ package org.springframework.cloud.sleuth.instrument.rxjava; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Configuration properties for RxJava tracing + * Configuration properties for RxJava tracing. * * @author Arthur Gavlyukovskiy * @since 1.0.12 @@ -31,6 +31,7 @@ public class SleuthRxJavaSchedulersProperties { * Thread names for which spans will not be sampled. */ private String[] ignoredthreads = { "HystrixMetricPoller", "^RxComputation.*$" }; + private Hook hook = new Hook(); public String[] getIgnoredthreads() { @@ -63,5 +64,7 @@ public class SleuthRxJavaSchedulersProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/SleuthSchedulingProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/SleuthSchedulingProperties.java index f707a5e0c..d546d2b37 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/SleuthSchedulingProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/SleuthSchedulingProperties.java @@ -19,7 +19,8 @@ package org.springframework.cloud.sleuth.instrument.scheduling; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Configuration properties for {@link org.springframework.scheduling.annotation.Scheduled} tracing + * Configuration properties for + * {@link org.springframework.scheduling.annotation.Scheduled} tracing. * * @author Arthur Gavlyukovskiy * @since 1.0.12 @@ -52,4 +53,5 @@ public class SleuthSchedulingProperties { public void setSkipPattern(String skipPattern) { this.skipPattern = skipPattern; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java index de9250940..6ff3d0139 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAspect.java @@ -28,9 +28,9 @@ import org.springframework.cloud.sleuth.util.SpanNameUtil; /** * 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. The name of the - * span will be the simple name of the class annotated with + * {@link org.springframework.scheduling.annotation.Scheduled} annotation. 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 @@ -38,16 +38,17 @@ import org.springframework.cloud.sleuth.util.SpanNameUtil; * @author Marcin Grzejszczak * @author Spencer Gibb * @since 1.0.0 - * * @see Tracing */ @Aspect public class TraceSchedulingAspect { private static final String CLASS_KEY = "class"; + private static final String METHOD_KEY = "method"; private final Tracer tracer; + private final Pattern skipPattern; public TraceSchedulingAspect(Tracer tracer, Pattern skipPattern) { @@ -62,11 +63,12 @@ public class TraceSchedulingAspect { } String spanName = SpanNameUtil.toLowerHyphen(pjp.getSignature().getName()); Span span = startOrContinueRenamedSpan(spanName); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { span.tag(CLASS_KEY, pjp.getTarget().getClass().getSimpleName()); span.tag(METHOD_KEY, pjp.getSignature().getName()); return pjp.proceed(); - } finally { + } + finally { span.finish(); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java index 0c60490ea..bb9190c66 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java @@ -36,7 +36,6 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy; * @author Michal Chmielarz, 4financeIT * @author Spencer Gibb * @since 1.0.0 - * * @see TraceSchedulingAspect */ @Configuration @@ -54,4 +53,5 @@ public class TraceSchedulingAutoConfiguration { return new TraceSchedulingAspect(tracer, Pattern.compile(sleuthSchedulingProperties.getSkipPattern())); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ClientSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ClientSampler.java index a66ef2294..c4c125715 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ClientSampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ClientSampler.java @@ -26,20 +26,24 @@ import java.lang.annotation.Target; import org.springframework.beans.factory.annotation.Qualifier; /** - * Annotate a client {@link brave.http.HttpSampler} that hsould be - * injected to {@link brave.http.HttpTracing} + * Annotate a client {@link brave.http.HttpSampler} that hsould be injected to + * {@link brave.http.HttpTracing}. * * @author Marcin Grzejszczak * @since 2.0.0 * @see Qualifier */ -@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, + ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @Qualifier(ClientSampler.NAME) public @interface ClientSampler { + /** + * Default name for Sleuth client sampler. + */ String NAME = "sleuthClientSampler"; } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ExceptionLoggingFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ExceptionLoggingFilter.java index f5617a6cb..69105cbab 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ExceptionLoggingFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ExceptionLoggingFilter.java @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.instrument.web; import java.io.IOException; + import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; @@ -28,8 +29,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - * Filter running after {@link brave.servlet.TracingFilter} - * that logs uncaught exceptions + * Filter running after {@link brave.servlet.TracingFilter} that logs uncaught exceptions. * * @author Marcin Grzejszczak * @since 2.0.0 @@ -38,23 +38,28 @@ class ExceptionLoggingFilter implements Filter { private static final Log log = LogFactory.getLog(ExceptionLoggingFilter.class); - @Override public void init(FilterConfig filterConfig) throws ServletException { + @Override + public void init(FilterConfig filterConfig) throws ServletException { } - @Override public void doFilter(ServletRequest request, ServletResponse response, + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { chain.doFilter(request, response); - } catch (Exception e) { + } + catch (Exception ex) { if (log.isErrorEnabled()) { - log.error("Uncaught exception thrown", e); + log.error("Uncaught exception thrown", ex); } - throw e; + throw ex; } } - @Override public void destroy() { + @Override + public void destroy() { } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ServerSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ServerSampler.java index 146956cb9..16389185e 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ServerSampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ServerSampler.java @@ -26,18 +26,24 @@ import java.lang.annotation.Target; import org.springframework.beans.factory.annotation.Qualifier; /** - * Annotate a server {@link brave.http.HttpSampler} that hsould be - * injected to {@link brave.http.HttpTracing} + * Annotate a server {@link brave.http.HttpSampler} that hsould be injected to + * {@link brave.http.HttpTracing}. * * @author Marcin Grzejszczak * @since 2.0.0 * @see Qualifier */ -@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE}) +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, + ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented @Qualifier(ServerSampler.NAME) public @interface ServerSampler { + + /** + * Default name for the Sleuth server sampler. + */ String NAME = "sleuthServerSampler"; + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ServletUtils.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ServletUtils.java index 5c0acdb71..0809e0704 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ServletUtils.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/ServletUtils.java @@ -20,14 +20,16 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** - * Utility class to retrieve data from Servlet - * HTTP request and response + * Utility class to retrieve data from Servlet HTTP request and response. * * @author Marcin Grzejszczak - * * @since 1.0.0 */ -class ServletUtils { +final class ServletUtils { + + private ServletUtils() { + + } static String getHeader(HttpServletRequest request, HttpServletResponse response, String name) { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SingleSkipPattern.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SingleSkipPattern.java index 62fc22883..eeb9821b5 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SingleSkipPattern.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SingleSkipPattern.java @@ -20,13 +20,15 @@ import java.util.Optional; import java.util.regex.Pattern; /** - * Provides a URL {@link Pattern} for spans that should be not sampled. - * The default implementation of {@link SkipPatternProvider} will harvest all + * Provides a URL {@link Pattern} for spans that should be not sampled. The default + * implementation of {@link SkipPatternProvider} will harvest all * {@link SingleSkipPattern}s and combine them in a single pattern * * @author Marcin Grzejszczak * @since 2.1.0 */ interface SingleSkipPattern { + Optional skipPattern(); + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProvider.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProvider.java index 7953d7496..8607798ab 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProvider.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProvider.java @@ -25,5 +25,7 @@ import java.util.regex.Pattern; * @since 2.0.0 */ public interface SkipPatternProvider { + Pattern skipPattern(); + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpClientParser.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpClientParser.java index 6a69a9eb0..ff72da893 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpClientParser.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpClientParser.java @@ -24,7 +24,7 @@ import brave.http.HttpClientParser; import org.springframework.cloud.sleuth.util.SpanNameUtil; /** - * An {@link HttpClientParser} that behaves like Sleuth in versions 1.x + * An {@link HttpClientParser} that behaves like Sleuth in versions 1.x. * * @author Marcin Grzejszczak * @since 2.0.0 @@ -32,8 +32,11 @@ import org.springframework.cloud.sleuth.util.SpanNameUtil; class SleuthHttpClientParser extends HttpClientParser { private static final String HOST_KEY = "http.host"; + private static final String METHOD_KEY = "http.method"; + private static final String PATH_KEY = "http.path"; + private static final String URL_KEY = "http.url"; private final TraceKeys traceKeys; @@ -42,24 +45,25 @@ class SleuthHttpClientParser extends HttpClientParser { this.traceKeys = traceKeys; } - @Override protected String spanName(HttpAdapter adapter, - Req req) { + @Override + protected String spanName(HttpAdapter adapter, Req req) { return getName(URI.create(adapter.url(req))); } - @Override public void request(HttpAdapter adapter, Req req, + @Override + public void request(HttpAdapter adapter, Req req, SpanCustomizer customizer) { super.request(adapter, req, customizer); String url = adapter.url(req); URI uri = URI.create(url); - addRequestTags(customizer, url, uri.getHost(), uri.getPath(), adapter.method(req)); - this.traceKeys.getHttp().getHeaders() - .forEach(s -> { - String headerValue = adapter.requestHeader(req, s); - if (headerValue != null) { - customizer.tag(key(s), headerValue); - } - }); + addRequestTags(customizer, url, uri.getHost(), uri.getPath(), + adapter.method(req)); + this.traceKeys.getHttp().getHeaders().forEach(((s) -> { + String headerValue = adapter.requestHeader(req, s); + if (headerValue != null) { + customizer.tag(key(s), headerValue); + } + })); } private String key(String key) { @@ -85,4 +89,5 @@ class SleuthHttpClientParser extends HttpClientParser { customizer.tag(PATH_KEY, path); customizer.tag(METHOD_KEY, method); } -} \ No newline at end of file + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpLegacyProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpLegacyProperties.java index db716c223..c6ccc6fc0 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpLegacyProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpLegacyProperties.java @@ -19,11 +19,17 @@ package org.springframework.cloud.sleuth.instrument.web; import org.springframework.boot.context.properties.ConfigurationProperties; /** + * Legacy HTTP Sleuth properties. + * * @author Marcin Grzejszczak * @since 2.0.0 */ @ConfigurationProperties("spring.sleuth.http.legacy") public class SleuthHttpLegacyProperties { + + /** + * Enables the legacy Sleuth setup. + */ private boolean enabled; public boolean isEnabled() { @@ -33,4 +39,5 @@ public class SleuthHttpLegacyProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpProperties.java index 792f53920..5bf2937ae 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpProperties.java @@ -19,8 +19,9 @@ package org.springframework.cloud.sleuth.instrument.web; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Sleuth HTTP settings + * Sleuth HTTP settings. * + * @author Marcin Grzejszczak * @since 2.0.0 */ @ConfigurationProperties("spring.sleuth.http") @@ -60,5 +61,7 @@ public class SleuthHttpProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpSampler.java index 598b51dad..134afd662 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpSampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpSampler.java @@ -22,7 +22,7 @@ import brave.http.HttpAdapter; import brave.http.HttpSampler; /** - * Doesn't sample a span if skip pattern is matched + * Doesn't sample a span if skip pattern is matched. * * @author Marcin Grzejszczak * @since 2.0.0 @@ -35,7 +35,8 @@ class SleuthHttpSampler extends HttpSampler { this.pattern = provider.skipPattern(); } - @Override public Boolean trySample(HttpAdapter adapter, Req request) { + @Override + public Boolean trySample(HttpAdapter adapter, Req request) { String url = adapter.path(request); boolean shouldSkip = this.pattern.matcher(url).matches(); if (shouldSkip) { @@ -43,4 +44,5 @@ class SleuthHttpSampler extends HttpSampler { } return null; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpServerParser.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpServerParser.java index 7c00f584d..d283db9a6 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpServerParser.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpServerParser.java @@ -25,7 +25,7 @@ import brave.http.HttpClientParser; import brave.http.HttpServerParser; /** - * An {@link HttpClientParser} that behaves like Sleuth in versions 1.x + * An {@link HttpClientParser} that behaves like Sleuth in versions 1.x. * * @author Marcin Grzejszczak * @since 2.0.0 @@ -35,6 +35,7 @@ class SleuthHttpServerParser extends HttpServerParser { private static final String STATUS_CODE_KEY = "http.status_code"; private final SleuthHttpClientParser clientParser; + private final ErrorParser errorParser; SleuthHttpServerParser(TraceKeys traceKeys, ErrorParser errorParser) { @@ -42,16 +43,18 @@ class SleuthHttpServerParser extends HttpServerParser { this.errorParser = errorParser; } - @Override protected ErrorParser errorParser() { + @Override + protected ErrorParser errorParser() { return this.errorParser; } - @Override protected String spanName(HttpAdapter adapter, - Req req) { + @Override + protected String spanName(HttpAdapter adapter, Req req) { return this.clientParser.spanName(adapter, req); } - @Override public void request(HttpAdapter adapter, Req req, + @Override + public void request(HttpAdapter adapter, Req req, SpanCustomizer customizer) { this.clientParser.request(adapter, req, customizer); } @@ -71,7 +74,8 @@ class SleuthHttpServerParser extends HttpServerParser { if (httpStatus == HttpServletResponse.SC_OK && error != null) { // Filter chain threw exception but the response status may not have been set // yet, so we have to guess. - customizer.tag(STATUS_CODE_KEY, String.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); + customizer.tag(STATUS_CODE_KEY, + String.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)); } // only tag valid http statuses else if (httpStatus >= 100 && (httpStatus < 200) || (httpStatus > 399)) { @@ -79,4 +83,5 @@ class SleuthHttpServerParser extends HttpServerParser { } error(httpStatus, error, customizer); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthWebProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthWebProperties.java index e452ae3cd..a54c52161 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthWebProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/SleuthWebProperties.java @@ -20,7 +20,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; /** - * Configuration properties for web tracing + * Configuration properties for web tracing. * * @author Arthur Gavlyukovskiy * @since 1.0.12 @@ -28,39 +28,47 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty; @ConfigurationProperties("spring.sleuth.web") public class SleuthWebProperties { - public static final String DEFAULT_SKIP_PATTERN = - "/api-docs.*|/autoconfig|/configprops|/dump|/health|/info|/metrics.*|/mappings|/trace|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html|/favicon.ico|/hystrix.stream|/application/.*|/actuator.*|/cloudfoundryapplication"; + /** + * Default set of skip patterns. + */ + public static final String DEFAULT_SKIP_PATTERN = "/api-docs.*|/autoconfig|/configprops|/dump|/health|/info|/metrics.*|/mappings|/trace|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html|/favicon.ico|/hystrix.stream|/application/.*|/actuator.*|/cloudfoundryapplication"; /** - * When true enables instrumentation for web applications + * When true enables instrumentation for web applications. */ private boolean enabled = true; /** - * Pattern for URLs that should be skipped in tracing + * Pattern for URLs that should be skipped in tracing. */ private String skipPattern = DEFAULT_SKIP_PATTERN; /** - * Additional pattern for URLs that should be skipped in tracing. - * This will be appended to the {@link SleuthWebProperties#skipPattern} + * Additional pattern for URLs that should be skipped in tracing. This will be + * appended to the {@link SleuthWebProperties#skipPattern}. */ private String additionalSkipPattern; - /** - * Order in which the tracing filters should be registered. - * Defaults to {@link TraceHttpAutoConfiguration#TRACING_FILTER_ORDER} + * Order in which the tracing filters should be registered. Defaults to + * {@link TraceHttpAutoConfiguration#TRACING_FILTER_ORDER}. */ private int filterOrder = TraceHttpAutoConfiguration.TRACING_FILTER_ORDER; /** - * Flag to toggle the presence of a filter that logs thrown exceptions + * Flag to toggle the presence of a filter that logs thrown exceptions. */ private boolean exceptionThrowingFilterEnabled = true; + /** + * Properties related to HTTP clients. + */ private Client client = new Client(); + public static String getDefaultSkipPattern() { + return DEFAULT_SKIP_PATTERN; + } + public boolean isEnabled() { return this.enabled; } @@ -85,10 +93,6 @@ public class SleuthWebProperties { this.additionalSkipPattern = additionalSkipPattern; } - public static String getDefaultSkipPattern() { - return DEFAULT_SKIP_PATTERN; - } - public int getFilterOrder() { return this.filterOrder; } @@ -114,14 +118,20 @@ public class SleuthWebProperties { this.client = client; } + /** + * Web client properties. + * @author Marcin Grzejszczak + */ public static class Client { + /** - * Pattern for URLs that should be skipped in client side tracing + * Pattern for URLs that should be skipped in client side tracing. */ private String skipPattern = ""; /** - * Enable interceptor injecting into {@link org.springframework.web.client.RestTemplate} + * Enable interceptor injecting into + * {@link org.springframework.web.client.RestTemplate}. */ private boolean enabled = true; @@ -140,8 +150,13 @@ public class SleuthWebProperties { public void setSkipPattern(String skipPattern) { this.skipPattern = skipPattern; } + } + /** + * Async computing properties. + * @author Marcin Grzejszczak + */ public static class Async { @NestedConfigurationProperty @@ -154,12 +169,18 @@ public class SleuthWebProperties { public void setClient(AsyncClient client) { this.client = client; } + } + /** + * Async client properties. + * @author Marcin Grzejszczak + */ public static class AsyncClient { /** - * Enable span information propagation for {@link org.springframework.http.client.AsyncClientHttpRequestFactory}. + * Enable span information propagation for + * {@link org.springframework.http.client.AsyncClientHttpRequestFactory}. */ private boolean enabled; @@ -181,12 +202,18 @@ public class SleuthWebProperties { public void setTemplate(Template template) { this.template = template; } + } + /** + * Async Rest Template properties. + * @author Marcin Grzejszczak + */ public static class Template { /** - * Enable span information propagation for {@link org.springframework.web.client.AsyncRestTemplate}. + * Enable span information propagation for + * {@link org.springframework.web.client.AsyncRestTemplate}. */ private boolean enabled; @@ -197,5 +224,7 @@ public class SleuthWebProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHttpAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHttpAutoConfiguration.java index 262e1966c..73b550065 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHttpAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHttpAutoConfiguration.java @@ -34,8 +34,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * related to HTTP based communication. + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} related to HTTP based communication. * * @author Marcin Grzejszczak * @since 2.0.0 @@ -44,30 +44,34 @@ import org.springframework.core.Ordered; @ConditionalOnBean(Tracing.class) @ConditionalOnProperty(name = "spring.sleuth.http.enabled", havingValue = "true", matchIfMissing = true) @AutoConfigureAfter(TraceWebAutoConfiguration.class) -@EnableConfigurationProperties({TraceKeys.class, SleuthHttpLegacyProperties.class}) +@EnableConfigurationProperties({ TraceKeys.class, SleuthHttpLegacyProperties.class }) public class TraceHttpAutoConfiguration { static final int TRACING_FILTER_ORDER = Ordered.HIGHEST_PRECEDENCE + 5; - @Autowired HttpClientParser clientParser; - @Autowired HttpServerParser serverParser; - @Autowired @ClientSampler HttpSampler clientSampler; - @Autowired(required = false) @ServerSampler HttpSampler serverSampler; + @Autowired + HttpClientParser clientParser; + + @Autowired + HttpServerParser serverParser; + + @Autowired + @ClientSampler + HttpSampler clientSampler; + + @Autowired(required = false) + @ServerSampler + HttpSampler serverSampler; @Bean @ConditionalOnMissingBean // NOTE: stable bean name as might be used outside sleuth - HttpTracing httpTracing( - Tracing tracing, - SkipPatternProvider provider) { + HttpTracing httpTracing(Tracing tracing, SkipPatternProvider provider) { HttpSampler serverSampler = combineUserProvidedSamplerWithSkipPatternSampler( provider); - return HttpTracing.newBuilder(tracing) - .clientParser(this.clientParser) - .serverParser(this.serverParser) - .clientSampler(this.clientSampler) - .serverSampler(serverSampler) - .build(); + return HttpTracing.newBuilder(tracing).clientParser(this.clientParser) + .serverParser(this.serverParser).clientSampler(this.clientSampler) + .serverSampler(serverSampler).build(); } private HttpSampler combineUserProvidedSamplerWithSkipPatternSampler( @@ -87,12 +91,12 @@ public class TraceHttpAutoConfiguration { } @Bean - @ConditionalOnProperty(name = "spring.sleuth.http.legacy.enabled", - havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = "spring.sleuth.http.legacy.enabled", havingValue = "false", matchIfMissing = true) @ConditionalOnMissingBean HttpClientParser httpClientParser(ErrorParser errorParser) { return new HttpClientParser() { - @Override protected ErrorParser errorParser() { + @Override + protected ErrorParser errorParser() { return errorParser; } }; @@ -100,13 +104,13 @@ public class TraceHttpAutoConfiguration { @Bean @ConditionalOnProperty(name = "spring.sleuth.http.legacy.enabled", havingValue = "true") - HttpServerParser sleuthHttpServerParser(TraceKeys traceKeys, ErrorParser errorParser) { + HttpServerParser sleuthHttpServerParser(TraceKeys traceKeys, + ErrorParser errorParser) { return new SleuthHttpServerParser(traceKeys, errorParser); } @Bean - @ConditionalOnProperty(name = "spring.sleuth.http.legacy.enabled", - havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(name = "spring.sleuth.http.legacy.enabled", havingValue = "false", matchIfMissing = true) @ConditionalOnMissingBean HttpServerParser defaultHttpServerParser() { return new HttpServerParser(); @@ -117,43 +121,69 @@ public class TraceHttpAutoConfiguration { HttpSampler sleuthClientSampler(SleuthWebProperties sleuthWebProperties) { return new PathMatchingHttpSampler(sleuthWebProperties); } + } +/** + * Composite Http Sampler. + * + * @author Adrian Cole + */ class CompositeHttpSampler extends HttpSampler { - private final HttpSampler left, right; + private final HttpSampler left; + + private final HttpSampler right; CompositeHttpSampler(HttpSampler left, HttpSampler right) { this.left = left; this.right = right; } - @Override public Boolean trySample(HttpAdapter adapter, Req request) { + @Override + public Boolean trySample(HttpAdapter adapter, Req request) { // If either decision is false, return false Boolean leftDecision = this.left.trySample(adapter, request); - if (Boolean.FALSE.equals(leftDecision)) return false; + if (Boolean.FALSE.equals(leftDecision)) { + return false; + } Boolean rightDecision = this.right.trySample(adapter, request); - if (Boolean.FALSE.equals(rightDecision)) return false; + if (Boolean.FALSE.equals(rightDecision)) { + return false; + } // If either decision is null, return the other - if (leftDecision == null) return rightDecision; - if (rightDecision == null) return leftDecision; + if (leftDecision == null) { + return rightDecision; + } + if (rightDecision == null) { + return leftDecision; + } // Neither are null and at least one is true return leftDecision && rightDecision; } + } +/** + * Http Sampler that looks at paths. + * + * @author Marcin Grzejszczak + */ class PathMatchingHttpSampler extends HttpSampler { + private final SleuthWebProperties properties; PathMatchingHttpSampler(SleuthWebProperties properties) { this.properties = properties; } - @Override public Boolean trySample(HttpAdapter adapter, Req request) { + @Override + public Boolean trySample(HttpAdapter adapter, Req request) { String path = adapter.path(request); if (path == null) { return null; } return path.matches(this.properties.getClient().getSkipPattern()) ? false : null; } -} \ No newline at end of file + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceKeys.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceKeys.java index c699f931d..303316a81 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceKeys.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceKeys.java @@ -22,12 +22,10 @@ import java.util.LinkedHashSet; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Well-known {@link brave.Span#tag(String, String) span tag} keys. - * With the deprecation we only left the option to pass a list of - * HTTP request headers that will be set as tags + * Well-known {@link brave.Span#tag(String, String) span tag} keys. With the deprecation + * we only left the option to pass a list of HTTP request headers that will be set as tags * * @since 1.0.0 - * * @deprecated the Brave's defaults are suggested to be used */ @ConfigurationProperties("spring.sleuth.keys") @@ -62,16 +60,18 @@ class TraceKeys { return this.prefix; } - public Collection getHeaders() { - return this.headers; - } - public void setPrefix(String prefix) { this.prefix = prefix; } + public Collection getHeaders() { + return this.headers; + } + public void setHeaders(Collection headers) { this.headers = headers; } + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceSpringDataBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceSpringDataBeanPostProcessor.java index fcc3d679b..8378b135f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceSpringDataBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceSpringDataBeanPostProcessor.java @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.instrument.web; import java.util.Collections; + import javax.servlet.http.HttpServletRequest; import brave.spring.webmvc.SpanCustomizingAsyncHandlerInterceptor; @@ -30,28 +31,31 @@ import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.HandlerMapping; /** - * Bean post processor that wraps Spring Data REST Controllers in named Spans + * Bean post processor that wraps Spring Data REST Controllers in named Spans. * * @author Marcin Grzejszczak * @since 1.0.3 */ class TraceSpringDataBeanPostProcessor implements BeanPostProcessor { - private static final Log log = LogFactory.getLog(TraceSpringDataBeanPostProcessor.class); + private static final Log log = LogFactory + .getLog(TraceSpringDataBeanPostProcessor.class); private final ApplicationContext applicationContext; - public TraceSpringDataBeanPostProcessor(ApplicationContext applicationContext) { + TraceSpringDataBeanPostProcessor(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof DelegatingHandlerMapping && !(bean instanceof TraceDelegatingHandlerMapping)) { + if (bean instanceof DelegatingHandlerMapping + && !(bean instanceof TraceDelegatingHandlerMapping)) { if (log.isDebugEnabled()) { - log.debug("Wrapping bean [" + beanName + "] of type [" + bean.getClass().getSimpleName() + - "] in its trace representation"); + log.debug("Wrapping bean [" + beanName + "] of type [" + + bean.getClass().getSimpleName() + + "] in its trace representation"); } return new TraceDelegatingHandlerMapping((DelegatingHandlerMapping) bean, this.applicationContext); @@ -68,9 +72,10 @@ class TraceSpringDataBeanPostProcessor implements BeanPostProcessor { private static class TraceDelegatingHandlerMapping extends DelegatingHandlerMapping { private final DelegatingHandlerMapping delegate; + private final ApplicationContext applicationContext; - public TraceDelegatingHandlerMapping(DelegatingHandlerMapping delegate, + TraceDelegatingHandlerMapping(DelegatingHandlerMapping delegate, ApplicationContext beanFactory) { super(Collections.emptyList()); this.delegate = delegate; @@ -85,12 +90,16 @@ class TraceSpringDataBeanPostProcessor implements BeanPostProcessor { @Override public HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { - HandlerExecutionChain handlerExecutionChain = this.delegate.getHandler(request); + HandlerExecutionChain handlerExecutionChain = this.delegate + .getHandler(request); if (handlerExecutionChain == null) { return null; } - handlerExecutionChain.addInterceptor(this.applicationContext.getBean(SpanCustomizingAsyncHandlerInterceptor.class)); + handlerExecutionChain.addInterceptor(this.applicationContext + .getBean(SpanCustomizingAsyncHandlerInterceptor.class)); return handlerExecutionChain; } + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java index 3faaacdf9..d3ecceaaa 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAspect.java @@ -34,29 +34,25 @@ import org.springframework.web.context.request.async.WebAsyncTask; * Aspect that adds tracing to *

    *

      - *
    • {@code RestController} annotated classes - * with public {@link Callable} methods
    • + *
    • {@code RestController} annotated classes with public {@link Callable} methods
    • *
    • {@link org.springframework.stereotype.Controller} annotated classes with public * {@link Callable} methods
    • - *
    • {@link org.springframework.stereotype.Controller} or - * {@code RestController} annotated classes with - * public {@link WebAsyncTask} methods
    • + *
    • {@link org.springframework.stereotype.Controller} or {@code RestController} + * annotated classes with public {@link WebAsyncTask} methods
    • *
    *

    * For controllers an around aspect is created that wraps the {@link Callable#call()} * method execution in {@link TraceCallable} *

    * - * This aspect will continue a span created by the TracingFilter. It will not create - * a new span - since the one in TracingFilter will wait until processing has been - * finished + * This aspect will continue a span created by the TracingFilter. It will not create a new + * span - since the one in TracingFilter 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.stereotype.Controller * @see org.springframework.web.client.RestOperations */ @@ -68,6 +64,7 @@ public class TraceWebAspect { .getLog(TraceWebAspect.class); private final Tracing tracing; + private final SpanNamer spanNamer; public TraceWebAspect(Tracing tracing, SpanNamer spanNamer) { @@ -76,22 +73,28 @@ public class TraceWebAspect { } @Pointcut("@within(org.springframework.web.bind.annotation.RestController)") - private void anyRestControllerAnnotated() { }// NOSONAR + private void anyRestControllerAnnotated() { + }// NOSONAR @Pointcut("@within(org.springframework.stereotype.Controller)") - private void anyControllerAnnotated() { } // NOSONAR + private void anyControllerAnnotated() { + } // NOSONAR @Pointcut("execution(public java.util.concurrent.Callable *(..))") - private void anyPublicMethodReturningCallable() { } // NOSONAR + private void anyPublicMethodReturningCallable() { + } // NOSONAR @Pointcut("(anyRestControllerAnnotated() || anyControllerAnnotated()) && anyPublicMethodReturningCallable()") - private void anyControllerOrRestControllerWithPublicAsyncMethod() { } // NOSONAR + private void anyControllerOrRestControllerWithPublicAsyncMethod() { + } // NOSONAR @Pointcut("execution(public org.springframework.web.context.request.async.WebAsyncTask *(..))") - private void anyPublicMethodReturningWebAsyncTask() { } // NOSONAR + private void anyPublicMethodReturningWebAsyncTask() { + } // NOSONAR @Pointcut("(anyRestControllerAnnotated() || anyControllerAnnotated()) && anyPublicMethodReturningWebAsyncTask()") - private void anyControllerOrRestControllerWithPublicWebAsyncTaskMethod() { } // NOSONAR + private void anyControllerOrRestControllerWithPublicWebAsyncTaskMethod() { + } // NOSONAR @Around("anyControllerOrRestControllerWithPublicAsyncMethod()") @SuppressWarnings("unchecked") @@ -108,7 +111,8 @@ public class TraceWebAspect { } @Around("anyControllerOrRestControllerWithPublicWebAsyncTaskMethod()") - public Object wrapWebAsyncTaskWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable { + public Object wrapWebAsyncTaskWithCorrelationId(ProceedingJoinPoint pjp) + throws Throwable { final WebAsyncTask webAsyncTask = (WebAsyncTask) pjp.proceed(); TraceContext currentSpan = this.tracing.currentTraceContext().get(); if (currentSpan == null) { @@ -120,9 +124,10 @@ public class TraceWebAspect { } Field callableField = WebAsyncTask.class.getDeclaredField("callable"); callableField.setAccessible(true); - callableField.set(webAsyncTask, new TraceCallable<>(this.tracing, this.spanNamer, - webAsyncTask.getCallable())); - } catch (NoSuchFieldException ex) { + callableField.set(webAsyncTask, new TraceCallable<>(this.tracing, + this.spanNamer, webAsyncTask.getCallable())); + } + catch (NoSuchFieldException ex) { log.warn("Cannot wrap webAsyncTask's callable with TraceCallable", ex); } return webAsyncTask; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index 27d696436..7557f7ea4 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -38,8 +38,8 @@ import org.springframework.util.StringUtils; /** * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration - * Auto-configuration} that sets up common building blocks for both reactive - * and servlet based web application. + * Auto-configuration} that sets up common building blocks for both reactive and servlet + * based web application. * * @author Marcin Grzejszczak * @since 1.0.0 @@ -51,33 +51,25 @@ import org.springframework.util.StringUtils; @EnableConfigurationProperties(SleuthWebProperties.class) public class TraceWebAutoConfiguration { - @Autowired(required = false) List patterns = new ArrayList<>(); + @Autowired(required = false) + List patterns = new ArrayList<>(); @Bean @ConditionalOnMissingBean SkipPatternProvider sleuthSkipPatternProvider() { - return () -> Pattern.compile(this.patterns - .stream() - .map(SingleSkipPattern::skipPattern) - .filter(Optional::isPresent) - .map(Optional::get) - .map(Pattern::pattern) - .collect(Collectors.joining("|"))); + return () -> Pattern + .compile(this.patterns.stream().map(SingleSkipPattern::skipPattern) + .filter(Optional::isPresent).map(Optional::get) + .map(Pattern::pattern).collect(Collectors.joining("|"))); } @Configuration @ConditionalOnClass(ManagementServerProperties.class) protected static class ManagementSkipPatternProviderConfig { - @Bean - @ConditionalOnBean(ManagementServerProperties.class) - public SingleSkipPattern skipPatternForManagementServerProperties( - final ManagementServerProperties managementServerProperties) { - return () -> getPatternForManagementServerProperties(managementServerProperties); - } - /** - * Sets or appends {@link ManagementServerProperties#getServlet()#getContextPath()} to the skip + * Sets or appends + * {@link ManagementServerProperties#getServlet()#getContextPath()} to the skip * pattern. If neither is available then sets the default one */ static Optional getPatternForManagementServerProperties( @@ -88,22 +80,24 @@ public class TraceWebAutoConfiguration { } return Optional.empty(); } + + @Bean + @ConditionalOnBean(ManagementServerProperties.class) + public SingleSkipPattern skipPatternForManagementServerProperties( + final ManagementServerProperties managementServerProperties) { + return () -> getPatternForManagementServerProperties( + managementServerProperties); + } + } @Configuration @ConditionalOnClass(ServerProperties.class) protected static class ServerSkipPatternProviderConfig { - @Bean - @ConditionalOnBean(ServerProperties.class) - public SingleSkipPattern skipPatternForServerProperties( - final ServerProperties serverProperties) { - return () -> getPatternForServerProperties(serverProperties); - } - /** - * Sets or appends {@link ServerProperties#getServlet()#getContextPath()} to the skip - * pattern. If neither is available then sets the default one + * Sets or appends {@link ServerProperties#getServlet()#getContextPath()} to the + * skip pattern. If neither is available then sets the default one */ static Optional getPatternForServerProperties( ServerProperties serverProperties) { @@ -113,22 +107,21 @@ public class TraceWebAutoConfiguration { } return Optional.empty(); } + + @Bean + @ConditionalOnBean(ServerProperties.class) + public SingleSkipPattern skipPatternForServerProperties( + final ServerProperties serverProperties) { + return () -> getPatternForServerProperties(serverProperties); + } + } @Configuration static class DefaultSkipPatternConfig { - @Bean - SingleSkipPattern defaultSkipPatternBean(SleuthWebProperties sleuthWebProperties) { - return () -> Optional.of( - Pattern.compile( - combinedPattern(sleuthWebProperties.getSkipPattern(), - sleuthWebProperties.getAdditionalSkipPattern()) - ) - ); - } - - private static String combinedPattern(String skipPattern, String additionalSkipPattern) { + private static String combinedPattern(String skipPattern, + String additionalSkipPattern) { String pattern = skipPattern; if (!StringUtils.hasText(skipPattern)) { pattern = SleuthWebProperties.DEFAULT_SKIP_PATTERN; @@ -138,7 +131,15 @@ public class TraceWebAutoConfiguration { } return pattern; } + + @Bean + SingleSkipPattern defaultSkipPatternBean( + SleuthWebProperties sleuthWebProperties) { + return () -> Optional.of( + Pattern.compile(combinedPattern(sleuthWebProperties.getSkipPattern(), + sleuthWebProperties.getAdditionalSkipPattern()))); + } + } } - diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFilter.java index be71c0885..c47dbbcdf 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFilter.java @@ -40,63 +40,63 @@ import reactor.core.publisher.Mono; import reactor.util.context.Context; /** - * A {@link WebFilter} that creates / continues / closes and detaches spans - * for a reactive web application. + * A {@link WebFilter} that creates / continues / closes and detaches spans for a reactive + * web application. * * @author Marcin Grzejszczak * @since 2.0.0 */ public final class TraceWebFilter implements WebFilter, Ordered { - private static final Log log = LogFactory.getLog(TraceWebFilter.class); - private static final String STATUS_CODE_KEY = "http.status_code"; - static final String MVC_CONTROLLER_CLASS_KEY = "mvc.controller.class"; - static final String MVC_CONTROLLER_METHOD_KEY = "mvc.controller.method"; - - protected static final String TRACE_REQUEST_ATTR = TraceWebFilter.class.getName() - + ".TRACE"; - private static final String TRACE_SPAN_WITHOUT_PARENT = TraceWebFilter.class.getName() - + ".SPAN_WITH_NO_PARENT"; - /** * If you register your filter before the {@link TraceWebFilter} then you will not * have the tracing context passed for you out of the box. That means that e.g. your * logs will not get correlated. */ public static final int ORDER = TraceHttpAutoConfiguration.TRACING_FILTER_ORDER; + protected static final String TRACE_REQUEST_ATTR = TraceWebFilter.class.getName() + + ".TRACE"; + static final String MVC_CONTROLLER_CLASS_KEY = "mvc.controller.class"; + static final String MVC_CONTROLLER_METHOD_KEY = "mvc.controller.method"; + static final Propagation.Getter GETTER = new Propagation.Getter() { - static final Propagation.Getter GETTER = - new Propagation.Getter() { + @Override + public String get(HttpHeaders carrier, String key) { + return carrier.getFirst(key); + } - @Override public String get(HttpHeaders carrier, String key) { - return carrier.getFirst(key); - } - - @Override public String toString() { - return "HttpHeaders::getFirst"; - } - }; - - public static WebFilter create(BeanFactory beanFactory) { - return new TraceWebFilter(beanFactory); - } - - Tracer tracer; - HttpServerHandler handler; - TraceContext.Extractor extractor; - SleuthWebProperties webProperties; + @Override + public String toString() { + return "HttpHeaders::getFirst"; + } + }; + private static final Log log = LogFactory.getLog(TraceWebFilter.class); + private static final String STATUS_CODE_KEY = "http.status_code"; + private static final String TRACE_SPAN_WITHOUT_PARENT = TraceWebFilter.class.getName() + + ".SPAN_WITH_NO_PARENT"; private final BeanFactory beanFactory; + Tracer tracer; + + HttpServerHandler handler; + + TraceContext.Extractor extractor; + + SleuthWebProperties webProperties; TraceWebFilter(BeanFactory beanFactory) { this.beanFactory = beanFactory; } + public static WebFilter create(BeanFactory beanFactory) { + return new TraceWebFilter(beanFactory); + } + @SuppressWarnings("unchecked") HttpServerHandler handler() { if (this.handler == null) { - this.handler = HttpServerHandler - .create(this.beanFactory.getBean(HttpTracing.class), - new TraceWebFilter.HttpAdapter()); + this.handler = HttpServerHandler.create( + this.beanFactory.getBean(HttpTracing.class), + new TraceWebFilter.HttpAdapter()); } return this.handler; } @@ -110,8 +110,8 @@ public final class TraceWebFilter implements WebFilter, Ordered { TraceContext.Extractor extractor() { if (this.extractor == null) { - this.extractor = this.beanFactory.getBean(HttpTracing.class) - .tracing().propagation().extractor(GETTER); + this.extractor = this.beanFactory.getBean(HttpTracing.class).tracing() + .propagation().extractor(GETTER); } return this.extractor; } @@ -123,7 +123,8 @@ public final class TraceWebFilter implements WebFilter, Ordered { return this.webProperties; } - @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + @Override + public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { if (tracer().currentSpan() != null) { // clear any previous trace tracer().withSpanInScope(null); @@ -134,62 +135,63 @@ public final class TraceWebFilter implements WebFilter, Ordered { } Span spanFromAttribute = getSpanFromAttribute(exchange); final String CONTEXT_ERROR = "sleuth.webfilter.context.error"; - return chain - .filter(exchange) - .compose(f -> f.then(Mono.subscriberContext()) - .onErrorResume(t -> Mono.subscriberContext() - .map(c -> c.put(CONTEXT_ERROR, t))) + return chain.filter(exchange) + .compose(f -> f.then(Mono.subscriberContext()).onErrorResume( + t -> Mono.subscriberContext().map(c -> c.put(CONTEXT_ERROR, t))) .flatMap(c -> { - //reactivate span from context + // reactivate span from context Span span = spanFromContext(c); Mono continuation; Throwable t = null; if (c.hasKey(CONTEXT_ERROR)) { t = c.get(CONTEXT_ERROR); continuation = Mono.error(t); - } else { + } + else { continuation = Mono.empty(); } String httpRoute = null; - Object attribute = exchange - .getAttribute(HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE); + Object attribute = exchange.getAttribute( + HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE); if (attribute instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) attribute; addClassMethodTag(handlerMethod, span); addClassNameTag(handlerMethod, span); - Object pattern = exchange - .getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); + Object pattern = exchange.getAttribute( + HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); httpRoute = pattern != null ? pattern.toString() : ""; } - addResponseTagsForSpanWithoutParent(exchange, exchange.getResponse(), span); + addResponseTagsForSpanWithoutParent(exchange, + exchange.getResponse(), span); DecoratedServerHttpResponse delegate = new DecoratedServerHttpResponse( - exchange.getResponse(), exchange.getRequest().getMethodValue(), - httpRoute); + exchange.getResponse(), + exchange.getRequest().getMethodValue(), httpRoute); handler().handleSend(delegate, t, span); if (log.isDebugEnabled()) { log.debug("Handled send of " + span); } return continuation; - }) - .subscriberContext(c -> { + }).subscriberContext(c -> { Span span; if (c.hasKey(Span.class)) { Span parent = c.get(Span.class); - span = tracer() - .nextSpan(TraceContextOrSamplingFlags.create(parent.context())) - .start(); + span = tracer().nextSpan(TraceContextOrSamplingFlags + .create(parent.context())).start(); if (log.isDebugEnabled()) { log.debug("Found span in reactor context" + span); } - } else { + } + else { if (spanFromAttribute != null) { span = spanFromAttribute; if (log.isDebugEnabled()) { log.debug("Found span in attribute " + span); } - } else { + } + else { span = handler().handleReceive(extractor(), - exchange.getRequest().getHeaders(), exchange.getRequest()); + exchange.getRequest().getHeaders(), + exchange.getRequest()); if (log.isDebugEnabled()) { log.debug("Handled receive of span " + span); } @@ -240,7 +242,8 @@ public final class TraceWebFilter implements WebFilter, Ordered { String methodName = ((HandlerMethod) handler).getMethod().getName(); span.tag(MVC_CONTROLLER_METHOD_KEY, methodName); if (log.isDebugEnabled()) { - log.debug("Adding a method tag with value [" + methodName + "] to a span " + span); + log.debug("Adding a method tag with value [" + methodName + "] to a span " + + span); } } } @@ -249,16 +252,19 @@ public final class TraceWebFilter implements WebFilter, Ordered { String className; if (handler instanceof HandlerMethod) { className = ((HandlerMethod) handler).getBeanType().getSimpleName(); - } else { + } + else { className = handler.getClass().getSimpleName(); } if (log.isDebugEnabled()) { - log.debug("Adding a class tag with value [" + className + "] to a span " + span); + log.debug("Adding a class tag with value [" + className + "] to a span " + + span); } span.tag(MVC_CONTROLLER_CLASS_KEY, className); } - @Override public int getOrder() { + @Override + public int getOrder() { return sleuthWebProperties().getFilterOrder(); } @@ -266,47 +272,56 @@ public final class TraceWebFilter implements WebFilter, Ordered { final String method, httpRoute; - DecoratedServerHttpResponse(ServerHttpResponse delegate, String method, String httpRoute) { + DecoratedServerHttpResponse(ServerHttpResponse delegate, String method, + String httpRoute) { super(delegate); this.method = method; this.httpRoute = httpRoute; } + } static final class HttpAdapter extends brave.http.HttpServerAdapter { - @Override public String method(ServerHttpRequest request) { + @Override + public String method(ServerHttpRequest request) { return request.getMethodValue(); } - @Override public String url(ServerHttpRequest request) { + @Override + public String url(ServerHttpRequest request) { return request.getURI().toString(); } - @Override public String requestHeader(ServerHttpRequest request, String name) { + @Override + public String requestHeader(ServerHttpRequest request, String name) { Object result = request.getHeaders().getFirst(name); return result != null ? result.toString() : null; } - @Override public Integer statusCode(ServerHttpResponse response) { - return response.getStatusCode() != null ? - response.getStatusCode().value() : null; + @Override + public Integer statusCode(ServerHttpResponse response) { + return response.getStatusCode() != null ? response.getStatusCode().value() + : null; } - @Override public String methodFromResponse(ServerHttpResponse response) { + @Override + public String methodFromResponse(ServerHttpResponse response) { if (response instanceof DecoratedServerHttpResponse) { return ((DecoratedServerHttpResponse) response).method; } return null; } - @Override public String route(ServerHttpResponse response) { + @Override + public String route(ServerHttpResponse response) { if (response instanceof DecoratedServerHttpResponse) { return ((DecoratedServerHttpResponse) response).httpRoute; } return null; } - } -} + } + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebMvcConfigurer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebMvcConfigurer.java index d55993e6c..f26fda9ec 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebMvcConfigurer.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebMvcConfigurer.java @@ -28,16 +28,19 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; * MVC Adapter that adds the {@link SpanCustomizingAsyncHandlerInterceptor} * * @author Marcin Grzejszczak - * * @since 1.0.3 */ @Configuration @Import(SpanCustomizingAsyncHandlerInterceptor.class) class TraceWebMvcConfigurer implements WebMvcConfigurer { - @Autowired ApplicationContext applicationContext; + + @Autowired + ApplicationContext applicationContext; @Override public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(this.applicationContext.getBean(SpanCustomizingAsyncHandlerInterceptor.class)); + registry.addInterceptor(this.applicationContext + .getBean(SpanCustomizingAsyncHandlerInterceptor.class)); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebServletAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebServletAutoConfiguration.java index 2e0c4e8a7..fda3392f7 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebServletAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebServletAutoConfiguration.java @@ -16,6 +16,8 @@ package org.springframework.cloud.sleuth.instrument.web; +import javax.servlet.DispatcherType; + import brave.Tracing; import brave.http.HttpTracing; import brave.servlet.TracingFilter; @@ -34,12 +36,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import static javax.servlet.DispatcherType.ASYNC; -import static javax.servlet.DispatcherType.ERROR; -import static javax.servlet.DispatcherType.FORWARD; -import static javax.servlet.DispatcherType.INCLUDE; -import static javax.servlet.DispatcherType.REQUEST; - /** * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration * Auto-configuration} enables tracing to HTTP requests. @@ -56,16 +52,16 @@ import static javax.servlet.DispatcherType.REQUEST; @Import(SpanCustomizingAsyncHandlerInterceptor.class) public class TraceWebServletAutoConfiguration { + /** + * Default filter order for the Http tracing filter. + */ public static final int TRACING_FILTER_ORDER = TraceHttpAutoConfiguration.TRACING_FILTER_ORDER; - /** - * Nested config that configures Web MVC if it's present (without adding a runtime - * dependency to it) - */ - @Configuration - @ConditionalOnClass(WebMvcConfigurer.class) - @Import(TraceWebMvcConfigurer.class) - protected static class TraceWebMvcAutoConfiguration { + @Bean + @ConditionalOnClass(name = "org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping") + public static TraceSpringDataBeanPostProcessor traceSpringDataBeanPostProcessor( + ApplicationContext applicationContext) { + return new TraceSpringDataBeanPostProcessor(applicationContext); } @Bean @@ -74,26 +70,26 @@ public class TraceWebServletAutoConfiguration { } @Bean - @ConditionalOnClass(name = "org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping") - public static TraceSpringDataBeanPostProcessor traceSpringDataBeanPostProcessor( - ApplicationContext applicationContext) { - return new TraceSpringDataBeanPostProcessor(applicationContext); - } - - @Bean - public FilterRegistrationBean traceWebFilter( - TracingFilter tracingFilter, SleuthWebProperties webProperties) { - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(tracingFilter); - filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE, REQUEST); + public FilterRegistrationBean traceWebFilter(TracingFilter tracingFilter, + SleuthWebProperties webProperties) { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean( + tracingFilter); + filterRegistrationBean.setDispatcherTypes(DispatcherType.ASYNC, + DispatcherType.ERROR, DispatcherType.FORWARD, DispatcherType.INCLUDE, + DispatcherType.REQUEST); filterRegistrationBean.setOrder(webProperties.getFilterOrder()); return filterRegistrationBean; } @Bean @ConditionalOnProperty(value = "spring.sleuth.web.exceptionThrowingFilterEnabled", matchIfMissing = true) - public FilterRegistrationBean exceptionThrowingFilter(SleuthWebProperties webProperties) { - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new ExceptionLoggingFilter()); - filterRegistrationBean.setDispatcherTypes(ASYNC, ERROR, FORWARD, INCLUDE, REQUEST); + public FilterRegistrationBean exceptionThrowingFilter( + SleuthWebProperties webProperties) { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean( + new ExceptionLoggingFilter()); + filterRegistrationBean.setDispatcherTypes(DispatcherType.ASYNC, + DispatcherType.ERROR, DispatcherType.FORWARD, DispatcherType.INCLUDE, + DispatcherType.REQUEST); filterRegistrationBean.setOrder(webProperties.getFilterOrder()); return filterRegistrationBean; } @@ -103,4 +99,16 @@ public class TraceWebServletAutoConfiguration { public TracingFilter tracingFilter(HttpTracing tracing) { return (TracingFilter) TracingFilter.create(tracing); } + + /** + * Nested config that configures Web MVC if it's present (without adding a runtime + * dependency to it). + */ + @Configuration + @ConditionalOnClass(WebMvcConfigurer.class) + @Import(TraceWebMvcConfigurer.class) + protected static class TraceWebMvcAutoConfiguration { + + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/SleuthWebClientEnabled.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/SleuthWebClientEnabled.java index a06dbad6e..444445eae 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/SleuthWebClientEnabled.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/SleuthWebClientEnabled.java @@ -25,14 +25,15 @@ import java.lang.annotation.Target; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; /** - * Helper annotation to enable Sleuth web client + * Helper annotation to enable Sleuth web client. * * @author Marcin Grzejszczak * @since 1.0.11 */ @Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.TYPE, ElementType.METHOD}) +@Target({ ElementType.TYPE, ElementType.METHOD }) @Documented @ConditionalOnProperty(value = "spring.sleuth.web.client.enabled", matchIfMissing = true) @interface SleuthWebClientEnabled { + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java index 923dd3eea..5fdf9e2d5 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java @@ -16,11 +16,12 @@ package org.springframework.cloud.sleuth.instrument.web.client; -import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import javax.annotation.PostConstruct; + import brave.http.HttpTracing; import brave.spring.web.TracingAsyncClientHttpRequestInterceptor; import org.springframework.beans.factory.annotation.Autowired; @@ -36,9 +37,9 @@ import org.springframework.http.client.AsyncClientHttpRequestInterceptor; import org.springframework.web.client.AsyncRestTemplate; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * enables span information propagation for {@link AsyncClientHttpRequestFactory} and - * {@link 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 @@ -55,8 +56,10 @@ public class TraceWebAsyncClientAutoConfiguration { static class AsyncRestTemplateConfig { @Bean - public TracingAsyncClientHttpRequestInterceptor asyncTracingClientHttpRequestInterceptor(HttpTracing httpTracing) { - return (TracingAsyncClientHttpRequestInterceptor) TracingAsyncClientHttpRequestInterceptor.create(httpTracing); + public TracingAsyncClientHttpRequestInterceptor asyncTracingClientHttpRequestInterceptor( + HttpTracing httpTracing) { + return (TracingAsyncClientHttpRequestInterceptor) TracingAsyncClientHttpRequestInterceptor + .create(httpTracing); } @Configuration @@ -79,6 +82,9 @@ public class TraceWebAsyncClientAutoConfiguration { } } } + } + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java index 12d365307..68d93dddf 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java @@ -96,23 +96,32 @@ public class TraceWebClientAutoConfiguration { static class RestTemplateConfig { @Bean - public TracingClientHttpRequestInterceptor tracingClientHttpRequestInterceptor(HttpTracing httpTracing) { - return (TracingClientHttpRequestInterceptor) TracingClientHttpRequestInterceptor.create(httpTracing); + public TracingClientHttpRequestInterceptor tracingClientHttpRequestInterceptor( + HttpTracing httpTracing) { + return (TracingClientHttpRequestInterceptor) TracingClientHttpRequestInterceptor + .create(httpTracing); } @Configuration protected static class TraceInterceptorConfiguration { - @Autowired private TracingClientHttpRequestInterceptor clientInterceptor; + @Autowired + private TracingClientHttpRequestInterceptor clientInterceptor; - @Bean @Order RestTemplateCustomizer traceRestTemplateCustomizer() { + @Bean + static TraceRestTemplateBeanPostProcessor traceRestTemplateBPP( + ListableBeanFactory beanFactory) { + return new TraceRestTemplateBeanPostProcessor(beanFactory); + } + + @Bean + @Order + RestTemplateCustomizer traceRestTemplateCustomizer() { return new TraceRestTemplateCustomizer(this.clientInterceptor); } - @Bean static TraceRestTemplateBeanPostProcessor traceRestTemplateBPP(ListableBeanFactory beanFactory) { - return new TraceRestTemplateBeanPostProcessor(beanFactory); - } } + } @Configuration @@ -124,6 +133,7 @@ public class TraceWebClientAutoConfiguration { HttpClientBuilder traceHttpClientBuilder(HttpTracing httpTracing) { return TracingHttpClientBuilder.create(httpTracing); } + } @Configuration @@ -135,41 +145,51 @@ public class TraceWebClientAutoConfiguration { HttpAsyncClientBuilder traceHttpAsyncClientBuilder(HttpTracing httpTracing) { return TracingHttpAsyncClientBuilder.create(httpTracing); } + } @ConditionalOnClass(WebClient.class) static class WebClientConfig { - @Bean static TraceWebClientBeanPostProcessor traceWebClientBeanPostProcessor(BeanFactory beanFactory) { + @Bean + static TraceWebClientBeanPostProcessor traceWebClientBeanPostProcessor( + BeanFactory beanFactory) { return new TraceWebClientBeanPostProcessor(beanFactory); } + } @Configuration @ConditionalOnClass(HttpClient.class) static class NettyConfiguration { + @Bean public NettyAspect traceNetyAspect(HttpTracing httpTracing) { return new NettyAspect(httpTracing); } + } @Configuration - @ConditionalOnClass({ UserInfoRestTemplateCustomizer.class, OAuth2RestTemplate.class }) + @ConditionalOnClass({ UserInfoRestTemplateCustomizer.class, + OAuth2RestTemplate.class }) protected static class TraceOAuthConfiguration { @Bean - UserInfoRestTemplateCustomizerBPP userInfoRestTemplateCustomizerBeanPostProcessor(BeanFactory beanFactory) { + UserInfoRestTemplateCustomizerBPP userInfoRestTemplateCustomizerBeanPostProcessor( + BeanFactory beanFactory) { return new UserInfoRestTemplateCustomizerBPP(beanFactory); } @Bean @ConditionalOnMissingBean - UserInfoRestTemplateCustomizer traceUserInfoRestTemplateCustomizer(BeanFactory beanFactory) { + UserInfoRestTemplateCustomizer traceUserInfoRestTemplateCustomizer( + BeanFactory beanFactory) { return new TraceUserInfoRestTemplateCustomizer(beanFactory); } - private static class UserInfoRestTemplateCustomizerBPP implements BeanPostProcessor { + private static class UserInfoRestTemplateCustomizerBPP + implements BeanPostProcessor { private final BeanFactory beanFactory; @@ -178,8 +198,8 @@ public class TraceWebClientAutoConfiguration { } @Override - public Object postProcessBeforeInitialization(Object bean, - String beanName) throws BeansException { + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { return bean; } @@ -187,17 +207,21 @@ public class TraceWebClientAutoConfiguration { public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { final BeanFactory beanFactory = this.beanFactory; - if (bean instanceof UserInfoRestTemplateCustomizer && - !(bean instanceof TraceUserInfoRestTemplateCustomizer)) { + if (bean instanceof UserInfoRestTemplateCustomizer + && !(bean instanceof TraceUserInfoRestTemplateCustomizer)) { return new TraceUserInfoRestTemplateCustomizer(beanFactory, bean); } return bean; } + } + } + } class RestTemplateInterceptorInjector { + private final ClientHttpRequestInterceptor interceptor; RestTemplateInterceptorInjector(ClientHttpRequestInterceptor interceptor) { @@ -215,14 +239,14 @@ class RestTemplateInterceptorInjector { } private boolean hasTraceInterceptor(RestTemplate restTemplate) { - for (ClientHttpRequestInterceptor interceptor : restTemplate - .getInterceptors()) { + for (ClientHttpRequestInterceptor interceptor : restTemplate.getInterceptors()) { if (interceptor instanceof TracingClientHttpRequestInterceptor) { return true; } } return false; } + } class TraceRestTemplateCustomizer implements RestTemplateCustomizer { @@ -233,10 +257,11 @@ class TraceRestTemplateCustomizer implements RestTemplateCustomizer { this.interceptor = interceptor; } - @Override public void customize(RestTemplate restTemplate) { - new RestTemplateInterceptorInjector(this.interceptor) - .inject(restTemplate); + @Override + public void customize(RestTemplate restTemplate) { + new RestTemplateInterceptorInjector(this.interceptor).inject(restTemplate); } + } class TraceRestTemplateBeanPostProcessor implements BeanPostProcessor { @@ -247,14 +272,16 @@ class TraceRestTemplateBeanPostProcessor implements BeanPostProcessor { this.beanFactory = beanFactory; } - @Override public Object postProcessBeforeInitialization(Object bean, String beanName) + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } - @Override public Object postProcessAfterInitialization(Object bean, String beanName) + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof RestTemplate) { + if (bean instanceof RestTemplate) { RestTemplate rt = (RestTemplate) bean; new RestTemplateInterceptorInjector(interceptor()).inject(rt); } @@ -270,23 +297,27 @@ class TraceRestTemplateBeanPostProcessor implements BeanPostProcessor { class LazyTracingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { private final BeanFactory beanFactory; + private TracingClientHttpRequestInterceptor interceptor; public LazyTracingClientHttpRequestInterceptor(BeanFactory beanFactory) { this.beanFactory = beanFactory; } - @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { return interceptor().intercept(request, body, execution); } private TracingClientHttpRequestInterceptor interceptor() { if (this.interceptor == null) { - this.interceptor = this.beanFactory.getBean(TracingClientHttpRequestInterceptor.class); + this.interceptor = this.beanFactory + .getBean(TracingClientHttpRequestInterceptor.class); } return this.interceptor; } + } @Aspect @@ -300,11 +331,13 @@ class NettyAspect { @Pointcut("execution(public * reactor.netty.http.client.HttpClient.RequestSender.send(..)) && args(function)") private void anyHttpClientRequestSending( - BiFunction> function) { } // NOSONAR + BiFunction> function) { + } // NOSONAR @Around("anyHttpClientRequestSending(function)") public Object wrapHttpClientRequestSending(ProceedingJoinPoint pjp, - BiFunction> function) throws Throwable { + BiFunction> function) + throws Throwable { return Mono.defer(() -> { try { return this.instrumentation.wrapHttpClientRequestSending(pjp, function); @@ -314,37 +347,37 @@ class NettyAspect { } }); } + } class TracingHttpClientInstrumentation { - private static final Log log = LogFactory.getLog(TracingHttpClientInstrumentation.class); static final Propagation.Setter SETTER = new Propagation.Setter() { - @Override public void put(HttpHeaders carrier, String key, String value) { + @Override + public void put(HttpHeaders carrier, String key, String value) { if (!carrier.contains(key)) { carrier.add(key, value); } } - @Override public String toString() { + @Override + public String toString() { return "HttpHeaders::add"; } }; - static final Propagation.Getter GETTER = new Propagation.Getter() { - @Override public String get(HttpHeaders carrier, String key) { + @Override + public String get(HttpHeaders carrier, String key) { return carrier.get(key); } - @Override public String toString() { + @Override + public String toString() { return "HttpHeaders::get"; } }; - - static TracingHttpClientInstrumentation create(HttpTracing httpTracing) { - return new TracingHttpClientInstrumentation(httpTracing); - } - + private static final Log log = LogFactory + .getLog(TracingHttpClientInstrumentation.class); final Tracer tracer; final HttpClientHandler handler; final TraceContext.Injector injector; @@ -357,35 +390,45 @@ class TracingHttpClientInstrumentation { this.httpTracing = httpTracing; } + static TracingHttpClientInstrumentation create(HttpTracing httpTracing) { + return new TracingHttpClientInstrumentation(httpTracing); + } + Mono wrapHttpClientRequestSending(ProceedingJoinPoint pjp, - BiFunction> function) throws Throwable { + BiFunction> function) + throws Throwable { // add headers and set CS final Span currentSpan = this.tracer.currentSpan(); final AtomicReference span = new AtomicReference<>(); - BiFunction> combinedFunction = - (req, nettyOutbound) -> { - try (Tracer.SpanInScope spanInScope = this.tracer.withSpanInScope(currentSpan)) { - io.netty.handler.codec.http.HttpHeaders originalHeaders = req - .requestHeaders().copy(); - io.netty.handler.codec.http.HttpHeaders tracedHeaders = req - .requestHeaders(); - span.set(this.handler.handleSend(this.injector, tracedHeaders, req)); - if (log.isDebugEnabled()) { - log.debug("Handled send of " + span.get()); - } - io.netty.handler.codec.http.HttpHeaders addedHeaders = tracedHeaders.copy(); - originalHeaders.forEach(header -> addedHeaders.remove(header.getKey())); - try (Tracer.SpanInScope clientInScope = this.tracer.withSpanInScope(span.get())) { - if (log.isDebugEnabled()) { - log.debug("Created a new client span for Netty client"); - } - return handle(function, new TracedHttpClientRequest(req, addedHeaders), nettyOutbound); - } + BiFunction> combinedFunction = ( + req, nettyOutbound) -> { + try (Tracer.SpanInScope spanInScope = this.tracer + .withSpanInScope(currentSpan)) { + io.netty.handler.codec.http.HttpHeaders originalHeaders = req + .requestHeaders().copy(); + io.netty.handler.codec.http.HttpHeaders tracedHeaders = req + .requestHeaders(); + span.set(this.handler.handleSend(this.injector, tracedHeaders, req)); + if (log.isDebugEnabled()) { + log.debug("Handled send of " + span.get()); + } + io.netty.handler.codec.http.HttpHeaders addedHeaders = tracedHeaders + .copy(); + originalHeaders.forEach(header -> addedHeaders.remove(header.getKey())); + try (Tracer.SpanInScope clientInScope = this.tracer + .withSpanInScope(span.get())) { + if (log.isDebugEnabled()) { + log.debug("Created a new client span for Netty client"); } - }; + return handle(function, + new TracedHttpClientRequest(req, addedHeaders), + nettyOutbound); + } + } + }; // run - Mono responseMono = - (Mono) pjp.proceed(new Object[] { combinedFunction }); + Mono responseMono = (Mono) pjp + .proceed(new Object[] { combinedFunction }); // get response return responseMono.doOnSuccessOrError((httpClientResponse, throwable) -> { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.get())) { @@ -400,96 +443,6 @@ class TracingHttpClientInstrumentation { }); } - /** - * The `org.springframework.cloud.gateway.filter.NettyRoutingFilter` in SC Gateway - * is adding only these headers that were set when the request came in. That means - * that adding any additional headers (via instrumentation) is completely ignored. - * That's why we're wrapping the `HttpClientRequest` in such a wrapper that - * when `setHeaders` is called (that clears any current headers), will also add - * the tracing headers - */ - static class TracedHttpClientRequest implements HttpClientRequest { - private HttpClientRequest delegate; - private final io.netty.handler.codec.http.HttpHeaders addedHeaders; - - TracedHttpClientRequest(HttpClientRequest delegate, HttpHeaders addedHeaders) { - this.delegate = delegate; - this.addedHeaders = addedHeaders; - } - - @Override public HttpClientRequest addCookie(Cookie cookie) { - this.delegate = this.delegate.addCookie(cookie); - return this; - } - - @Override public HttpClientRequest addHeader(CharSequence name, - CharSequence value) { - this.delegate = this.delegate.addHeader(name, value); - return this; - } - - @Override public boolean hasSentHeaders() { - return this.delegate.hasSentHeaders(); - } - - @Override public HttpClientRequest header(CharSequence name, CharSequence value) { - this.delegate = this.delegate.header(name, value); - return this; - } - - @Override public HttpClientRequest headers(HttpHeaders headers) { - HttpHeaders copy = headers.copy(); - copy.add(this.addedHeaders); - this.delegate = this.delegate.headers(copy); - return this; - } - - @Override public boolean isFollowRedirect() { - return this.delegate.isFollowRedirect(); - } - - @Override public HttpClientRequest keepAlive(boolean keepAlive) { - this.delegate = this.delegate.keepAlive(keepAlive); - return this; - } - - @Override public String[] redirectedFrom() { - return this.delegate.redirectedFrom(); - } - - @Override public HttpHeaders requestHeaders() { - return this.delegate.requestHeaders(); - } - - @Override public Map> cookies() { - return this.delegate.cookies(); - } - - @Override public boolean isKeepAlive() { - return this.delegate.isKeepAlive(); - } - - @Override public boolean isWebsocket() { - return this.delegate.isWebsocket(); - } - - @Override public HttpMethod method() { - return this.delegate.method(); - } - - @Override public String path() { - return this.delegate.path(); - } - - @Override public String uri() { - return this.delegate.uri(); - } - - @Override public HttpVersion version() { - return this.delegate.version(); - } - } - private Publisher handle( BiFunction> handler, HttpClientRequest req, NettyOutbound nettyOutbound) { @@ -499,31 +452,144 @@ class TracingHttpClientInstrumentation { return nettyOutbound; } + /** + * The `org.springframework.cloud.gateway.filter.NettyRoutingFilter` in SC Gateway is + * adding only these headers that were set when the request came in. That means that + * adding any additional headers (via instrumentation) is completely ignored. That's + * why we're wrapping the `HttpClientRequest` in such a wrapper that when `setHeaders` + * is called (that clears any current headers), will also add the tracing headers + */ + static class TracedHttpClientRequest implements HttpClientRequest { + + private final io.netty.handler.codec.http.HttpHeaders addedHeaders; + private HttpClientRequest delegate; + + TracedHttpClientRequest(HttpClientRequest delegate, HttpHeaders addedHeaders) { + this.delegate = delegate; + this.addedHeaders = addedHeaders; + } + + @Override + public HttpClientRequest addCookie(Cookie cookie) { + this.delegate = this.delegate.addCookie(cookie); + return this; + } + + @Override + public HttpClientRequest addHeader(CharSequence name, CharSequence value) { + this.delegate = this.delegate.addHeader(name, value); + return this; + } + + @Override + public boolean hasSentHeaders() { + return this.delegate.hasSentHeaders(); + } + + @Override + public HttpClientRequest header(CharSequence name, CharSequence value) { + this.delegate = this.delegate.header(name, value); + return this; + } + + @Override + public HttpClientRequest headers(HttpHeaders headers) { + HttpHeaders copy = headers.copy(); + copy.add(this.addedHeaders); + this.delegate = this.delegate.headers(copy); + return this; + } + + @Override + public boolean isFollowRedirect() { + return this.delegate.isFollowRedirect(); + } + + @Override + public HttpClientRequest keepAlive(boolean keepAlive) { + this.delegate = this.delegate.keepAlive(keepAlive); + return this; + } + + @Override + public String[] redirectedFrom() { + return this.delegate.redirectedFrom(); + } + + @Override + public HttpHeaders requestHeaders() { + return this.delegate.requestHeaders(); + } + + @Override + public Map> cookies() { + return this.delegate.cookies(); + } + + @Override + public boolean isKeepAlive() { + return this.delegate.isKeepAlive(); + } + + @Override + public boolean isWebsocket() { + return this.delegate.isWebsocket(); + } + + @Override + public HttpMethod method() { + return this.delegate.method(); + } + + @Override + public String path() { + return this.delegate.path(); + } + + @Override + public String uri() { + return this.delegate.uri(); + } + + @Override + public HttpVersion version() { + return this.delegate.version(); + } + + } + static final class HttpAdapter extends brave.http.HttpClientAdapter { - @Override public String method(HttpClientRequest request) { + @Override + public String method(HttpClientRequest request) { return request.method().name(); } - @Override public String url(HttpClientRequest request) { + @Override + public String url(HttpClientRequest request) { return request.uri(); } - @Override public String requestHeader(HttpClientRequest request, String name) { + @Override + public String requestHeader(HttpClientRequest request, String name) { Object result = request.requestHeaders().get(name); return result != null ? result.toString() : ""; } - @Override public Integer statusCode(HttpClientResponse response) { + @Override + public Integer statusCode(HttpClientResponse response) { return response.status().code(); } + } + } class TraceUserInfoRestTemplateCustomizer implements UserInfoRestTemplateCustomizer { private final BeanFactory beanFactory; + private final Object delegate; TraceUserInfoRestTemplateCustomizer(BeanFactory beanFactory) { @@ -536,12 +602,14 @@ class TraceUserInfoRestTemplateCustomizer implements UserInfoRestTemplateCustomi this.delegate = bean; } - @Override public void customize(OAuth2RestTemplate template) { - final TracingClientHttpRequestInterceptor interceptor = - this.beanFactory.getBean(TracingClientHttpRequestInterceptor.class); + @Override + public void customize(OAuth2RestTemplate template) { + final TracingClientHttpRequestInterceptor interceptor = this.beanFactory + .getBean(TracingClientHttpRequestInterceptor.class); new RestTemplateInterceptorInjector(interceptor).inject(template); if (this.delegate != null) { ((UserInfoRestTemplateCustomizer) this.delegate).customize(template); } } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientBeanPostProcessor.java index ec231112f..e5541705d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientBeanPostProcessor.java @@ -39,8 +39,8 @@ import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; /** - * {@link BeanPostProcessor} to wrap a {@link WebClient} instance into - * its trace representation + * {@link BeanPostProcessor} to wrap a {@link WebClient} instance into its trace + * representation * * @author Marcin Grzejszczak * @since 2.0.0 @@ -53,20 +53,21 @@ class TraceWebClientBeanPostProcessor implements BeanPostProcessor { this.beanFactory = beanFactory; } - @Override public Object postProcessBeforeInitialization(Object bean, String beanName) + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } - @Override public Object postProcessAfterInitialization(Object bean, String beanName) + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof WebClient) { WebClient webClient = (WebClient) bean; - return webClient - .mutate() - .filters(addTraceExchangeFilterFunctionIfNotPresent()) - .build(); - } else if (bean instanceof WebClient.Builder) { + return webClient.mutate() + .filters(addTraceExchangeFilterFunctionIfNotPresent()).build(); + } + else if (bean instanceof WebClient.Builder) { WebClient.Builder webClientBuilder = (WebClient.Builder) bean; return webClientBuilder.filters(addTraceExchangeFilterFunctionIfNotPresent()); } @@ -75,46 +76,41 @@ class TraceWebClientBeanPostProcessor implements BeanPostProcessor { private Consumer> addTraceExchangeFilterFunctionIfNotPresent() { return functions -> { - if (functions - .stream() + if (functions.stream() .noneMatch(f -> f instanceof TraceExchangeFilterFunction)) { functions.add(new TraceExchangeFilterFunction(this.beanFactory)); } }; } + } class TraceExchangeFilterFunction implements ExchangeFilterFunction { - private static final Log log = LogFactory.getLog( - TraceExchangeFilterFunction.class); - private static final String CLIENT_SPAN_KEY = "sleuth.webclient.clientSpan"; - - static final Propagation.Setter SETTER = - new Propagation.Setter() { - @Override public void put(ClientRequest.Builder carrier, String key, String value) { - carrier.header(key, value); - } - - @Override public String toString() { - return "ClientRequest.Builder::header"; - } - }; + static final Propagation.Setter SETTER = new Propagation.Setter() { + @Override + public void put(ClientRequest.Builder carrier, String key, String value) { + carrier.header(key, value); + } + @Override + public String toString() { + return "ClientRequest.Builder::header"; + } + }; static final Propagation.Getter GETTER = new Propagation.Getter() { - @Override public String get(ClientRequest carrier, String key) { + @Override + public String get(ClientRequest carrier, String key) { return carrier.headers().getFirst(key); } - @Override public String toString() { + @Override + public String toString() { return "HttpHeaders::getFirst"; } }; - - public static ExchangeFilterFunction create(BeanFactory beanFactory) { - return new TraceExchangeFilterFunction(beanFactory); - } - + private static final Log log = LogFactory.getLog(TraceExchangeFilterFunction.class); + private static final String CLIENT_SPAN_KEY = "sleuth.webclient.clientSpan"; final BeanFactory beanFactory; Tracer tracer; HttpTracing httpTracing; @@ -125,38 +121,43 @@ class TraceExchangeFilterFunction implements ExchangeFilterFunction { this.beanFactory = beanFactory; } - @Override public Mono filter(ClientRequest request, - ExchangeFunction next) { + public static ExchangeFilterFunction create(BeanFactory beanFactory) { + return new TraceExchangeFilterFunction(beanFactory); + } + + @Override + public Mono filter(ClientRequest request, ExchangeFunction next) { final ClientRequest.Builder builder = ClientRequest.from(request); - Mono exchange = Mono - .defer(() -> next.exchange(builder.build())) - .cast(Object.class) - .onErrorResume(Mono::just) - .zipWith(Mono.subscriberContext()) - .flatMap(anyAndContext -> { + Mono exchange = Mono.defer(() -> next.exchange(builder.build())) + .cast(Object.class).onErrorResume(Mono::just) + .zipWith(Mono.subscriberContext()).flatMap(anyAndContext -> { Object any = anyAndContext.getT1(); Span clientSpan = anyAndContext.getT2().get(CLIENT_SPAN_KEY); Mono continuation; final Tracer.SpanInScope ws = tracer().withSpanInScope(clientSpan); - if (any instanceof Throwable) { - continuation = Mono.error((Throwable) any); - } else { - continuation = Mono.just((ClientResponse) any); - } - return continuation.doAfterSuccessOrError( - (clientResponse, throwable1) -> { + if (any instanceof Throwable) { + continuation = Mono.error((Throwable) any); + } + else { + continuation = Mono.just((ClientResponse) any); + } + return continuation + .doAfterSuccessOrError((clientResponse, throwable1) -> { Throwable throwable = throwable1; - if (clientResponse == null || clientResponse.statusCode() == null) { + if (clientResponse == null + || clientResponse.statusCode() == null) { if (log.isDebugEnabled()) { log.debug( "No response was returned. Will close the span [" + clientSpan + "]"); } - handleReceive(clientSpan, ws, clientResponse, throwable); + handleReceive(clientSpan, ws, clientResponse, + throwable); return; } - boolean error = clientResponse.statusCode().is4xxClientError() || - clientResponse.statusCode().is5xxServerError(); + boolean error = clientResponse.statusCode() + .is4xxClientError() + || clientResponse.statusCode().is5xxServerError(); if (error) { if (log.isDebugEnabled()) { log.debug( @@ -164,27 +165,30 @@ class TraceExchangeFilterFunction implements ExchangeFilterFunction { + clientSpan + "]"); } throwable = new RestClientException( - "Status code of the response is [" + clientResponse.statusCode() - .value() + "] and the reason is [" + clientResponse - .statusCode().getReasonPhrase() + "]"); + "Status code of the response is [" + + clientResponse.statusCode().value() + + "] and the reason is [" + + clientResponse.statusCode() + .getReasonPhrase() + + "]"); } handleReceive(clientSpan, ws, clientResponse, throwable); }); - }) - .subscriberContext(c -> { + }).subscriberContext(c -> { if (log.isDebugEnabled()) { log.debug("Instrumenting WebClient call"); } Span parent = c.getOrDefault(Span.class, null); - Span clientSpan = handler().handleSend(injector(), builder, - request, tracer().nextSpan()); + Span clientSpan = handler().handleSend(injector(), builder, request, + tracer().nextSpan()); if (log.isDebugEnabled()) { log.debug("Handled send of " + clientSpan); } if (parent == null) { c = c.put(Span.class, clientSpan); if (log.isDebugEnabled()) { - log.debug("Reactor Context got injected with the client span " + clientSpan); + log.debug("Reactor Context got injected with the client span " + + clientSpan); } } return c.put(CLIENT_SPAN_KEY, clientSpan); @@ -201,8 +205,9 @@ class TraceExchangeFilterFunction implements ExchangeFilterFunction { @SuppressWarnings("unchecked") HttpClientHandler handler() { if (this.handler == null) { - this.handler = HttpClientHandler - .create(this.beanFactory.getBean(HttpTracing.class), new TraceExchangeFilterFunction.HttpAdapter()); + this.handler = HttpClientHandler.create( + this.beanFactory.getBean(HttpTracing.class), + new TraceExchangeFilterFunction.HttpAdapter()); } return this.handler; } @@ -223,31 +228,36 @@ class TraceExchangeFilterFunction implements ExchangeFilterFunction { TraceContext.Injector injector() { if (this.injector == null) { - this.injector = this.beanFactory.getBean(HttpTracing.class) - .tracing().propagation().injector(SETTER); + this.injector = this.beanFactory.getBean(HttpTracing.class).tracing() + .propagation().injector(SETTER); } return this.injector; } - static final class HttpAdapter extends brave.http.HttpClientAdapter { - @Override public String method(ClientRequest request) { + @Override + public String method(ClientRequest request) { return request.method().name(); } - @Override public String url(ClientRequest request) { + @Override + public String url(ClientRequest request) { return request.url().toString(); } - @Override public String requestHeader(ClientRequest request, String name) { + @Override + public String requestHeader(ClientRequest request, String name) { Object result = request.headers().getFirst(name); return result != null ? result.toString() : null; } - @Override public Integer statusCode(ClientResponse response) { + @Override + public Integer statusCode(ClientResponse response) { return response.statusCode().value(); } + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignContextBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignContextBeanPostProcessor.java index 6f5b5652f..1efd61f46 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignContextBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignContextBeanPostProcessor.java @@ -25,7 +25,6 @@ import org.springframework.cloud.openfeign.FeignContext; * Post processor that wraps Feign Context in its tracing representations. * * @author Marcin Grzejszczak - * * @since 1.0.2 */ final class FeignContextBeanPostProcessor implements BeanPostProcessor { @@ -54,4 +53,5 @@ final class FeignContextBeanPostProcessor implements BeanPostProcessor { private TraceFeignObjectWrapper traceFeignObjectWrapper() { return new TraceFeignObjectWrapper(this.beanFactory); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/LazyClient.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/LazyClient.java index 4495f3a50..f050f714a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/LazyClient.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/LazyClient.java @@ -23,9 +23,15 @@ import feign.Request; import feign.Response; import org.springframework.beans.factory.BeanFactory; -class LazyClient implements Client { +/** + * Lazy implementation of the Feign Client. + * + * @author Marcin Grzejszczak + */ +class LazyClient implements Client { private final BeanFactory beanFactory; + private final Client delegate; private TraceFeignObjectWrapper wrapper; @@ -35,8 +41,8 @@ class LazyClient implements Client { this.delegate = delegate; } - @Override public Response execute(Request request, Request.Options options) - throws IOException { + @Override + public Response execute(Request request, Request.Options options) throws IOException { return ((Client) wrapper().wrap(this.delegate)).execute(request, options); } @@ -46,4 +52,5 @@ class LazyClient implements Client { } return this.wrapper; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/LazyTracingFeignClient.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/LazyTracingFeignClient.java index c93cc9c4b..c8f72103a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/LazyTracingFeignClient.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/LazyTracingFeignClient.java @@ -27,7 +27,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactory; /** - * Lazilly resolves the Trace Feign Client + * Lazilly resolves the Trace Feign Client. * * @author Marcin Grzejszczak * @since 2.0.0 @@ -35,29 +35,30 @@ import org.springframework.beans.factory.BeanFactory; class LazyTracingFeignClient implements Client { private static final Log log = LogFactory.getLog(LazyTracingFeignClient.class); - - private Client tracingFeignClient; - private HttpTracing httpTracing; private final BeanFactory beanFactory; private final Client delegate; + private Client tracingFeignClient; + private HttpTracing httpTracing; LazyTracingFeignClient(BeanFactory beanFactory, Client delegate) { this.beanFactory = beanFactory; this.delegate = delegate; } - @Override public Response execute(Request request, Request.Options options) - throws IOException { + @Override + public Response execute(Request request, Request.Options options) throws IOException { if (log.isDebugEnabled()) { - log.debug("Sending a request via tracing feign client [" + tracingFeignClient() + "] " - + "and the delegate [" + this.delegate + "]"); + log.debug( + "Sending a request via tracing feign client [" + tracingFeignClient() + + "] " + "and the delegate [" + this.delegate + "]"); } return tracingFeignClient().execute(request, options); } private Client tracingFeignClient() { if (this.tracingFeignClient == null) { - this.tracingFeignClient = TracingFeignClient.create(httpTracing(), this.delegate); + this.tracingFeignClient = TracingFeignClient.create(httpTracing(), + this.delegate); } return this.tracingFeignClient; } @@ -68,4 +69,5 @@ class LazyTracingFeignClient implements Client { } return this.httpTracing; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/NeverRetry.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/NeverRetry.java index c82b12fe2..3c6f2115e 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/NeverRetry.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/NeverRetry.java @@ -22,9 +22,16 @@ import feign.Retryer; /** * This is essentially the same implementation of a Retryer that is in newer versions of * Feign. For the 1.0.x stream we add it here. + * * @author Ryan Baxter */ public class NeverRetry implements Retryer { + + /** + * Default retry entry. + */ + public static final NeverRetry INSTANCE = new NeverRetry(); + @Override public void continueOrPropagate(RetryableException e) { throw e; @@ -35,5 +42,4 @@ public class NeverRetry implements Retryer { return this; } - public static final NeverRetry INSTANCE = new NeverRetry(); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/OkHttpFeignClientBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/OkHttpFeignClientBeanPostProcessor.java index 4c59cdfb7..f7b155e2d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/OkHttpFeignClientBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/OkHttpFeignClientBeanPostProcessor.java @@ -23,10 +23,9 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.BeanPostProcessor; /** - * Post processor that wraps takes care of the OkHttp Feign Client instrumentation + * Post processor that wraps takes care of the OkHttp Feign Client instrumentation. * * @author Marcin Grzejszczak - * * @since 1.1.3 */ final class OkHttpFeignClientBeanPostProcessor implements BeanPostProcessor { @@ -51,4 +50,5 @@ final class OkHttpFeignClientBeanPostProcessor implements BeanPostProcessor { throws BeansException { return bean; } -} \ No newline at end of file + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthFeignBuilder.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthFeignBuilder.java index 7c0a2afca..b25207b8f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthFeignBuilder.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthFeignBuilder.java @@ -24,29 +24,30 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; /** - * Contains {@link Feign.Builder} implementation with tracing components - * that close spans on completion of request processing. + * Contains {@link Feign.Builder} implementation with tracing components that close spans + * on completion of request processing. * * @author Marcin Grzejszczak - * * @since 1.0.0 */ final class SleuthFeignBuilder { - private SleuthFeignBuilder() {} + private SleuthFeignBuilder() { + } static Feign.Builder builder(BeanFactory beanFactory) { - return Feign.builder().retryer(Retryer.NEVER_RETRY) - .client(client(beanFactory)); + return Feign.builder().retryer(Retryer.NEVER_RETRY).client(client(beanFactory)); } private static Client client(BeanFactory beanFactory) { try { Client client = beanFactory.getBean(Client.class); return new LazyClient(beanFactory, client); - } catch (BeansException e) { + } + catch (BeansException ex) { return TracingFeignClient.create(beanFactory.getBean(HttpTracing.class), new Client.Default(null, null)); } } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthFeignProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthFeignProperties.java index da8a2bdf0..f538a8294 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthFeignProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthFeignProperties.java @@ -19,7 +19,7 @@ package org.springframework.cloud.sleuth.instrument.web.client.feign; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Configuration properties for Feign + * Configuration properties for Feign. * * @author Marcin Grzejszczak * @since 2.0.2 @@ -28,7 +28,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; public class SleuthFeignProperties { /** - * When true enables instrumentation for feign + * When true enables instrumentation for feign. */ private boolean enabled = true; @@ -39,4 +39,5 @@ public class SleuthFeignProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthHystrixFeignBuilder.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthHystrixFeignBuilder.java index 48d5ace1c..9ec11f609 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthHystrixFeignBuilder.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/SleuthHystrixFeignBuilder.java @@ -26,16 +26,16 @@ import org.springframework.beans.factory.BeanFactory; /** * Contains {@link Feign.Builder} implementation that delegates execution - * {@link HystrixFeign} with tracing components - * that close spans upon completion of request processing. + * {@link HystrixFeign} with tracing components that close spans upon completion of + * request processing. * * @author Marcin Grzejszczak - * * @since 1.0.4 */ final class SleuthHystrixFeignBuilder { - private SleuthHystrixFeignBuilder() {} + private SleuthHystrixFeignBuilder() { + } static Feign.Builder builder(BeanFactory beanFactory) { return HystrixFeign.builder().retryer(Retryer.NEVER_RETRY) @@ -46,9 +46,11 @@ final class SleuthHystrixFeignBuilder { try { Client client = beanFactory.getBean(Client.class); return new LazyClient(beanFactory, client); - } catch (BeansException e) { + } + catch (BeansException ex) { return TracingFeignClient.create(beanFactory.getBean(HttpTracing.class), new Client.Default(null, null)); } } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignAspect.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignAspect.java index 41037e30e..1af56b3f6 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignAspect.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignAspect.java @@ -28,7 +28,7 @@ import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.factory.BeanFactory; /** - * Aspect for Feign clients so that you can autowire your custom components + * Aspect for Feign clients so that you can autowire your custom components. * * @author Marcin Grzejszczak * @since 1.1.2 @@ -57,10 +57,12 @@ class TraceFeignAspect { return pjp.proceed(); } - Object executeTraceFeignClient(Object bean, ProceedingJoinPoint pjp) throws IOException { + Object executeTraceFeignClient(Object bean, ProceedingJoinPoint pjp) + throws IOException { Object[] args = pjp.getArgs(); Request request = (Request) args[0]; Request.Options options = (Request.Options) args[1]; return ((Client) bean).execute(request, options); } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignClientAutoConfiguration.java index c3829f2b2..28b4d805f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignClientAutoConfiguration.java @@ -47,12 +47,14 @@ import org.springframework.context.annotation.Scope; @ConditionalOnClass({ Client.class, FeignContext.class }) @ConditionalOnBean(HttpTracing.class) @AutoConfigureBefore(FeignAutoConfiguration.class) -@AutoConfigureAfter({SleuthHystrixAutoConfiguration.class, TraceHttpAutoConfiguration.class}) +@AutoConfigureAfter({ SleuthHystrixAutoConfiguration.class, + TraceHttpAutoConfiguration.class }) public class TraceFeignClientAutoConfiguration { @Bean @Scope("prototype") - @ConditionalOnClass(name = {"com.netflix.hystrix.HystrixCommand", "feign.hystrix.HystrixFeign"}) + @ConditionalOnClass(name = { "com.netflix.hystrix.HystrixCommand", + "feign.hystrix.HystrixFeign" }) @ConditionalOnProperty(name = "feign.hystrix.enabled", havingValue = "true") Feign.Builder feignHystrixBuilder(BeanFactory beanFactory) { return SleuthHystrixFeignBuilder.builder(beanFactory); @@ -66,30 +68,38 @@ public class TraceFeignClientAutoConfiguration { return SleuthFeignBuilder.builder(beanFactory); } + @Bean + TraceFeignObjectWrapper traceFeignObjectWrapper(BeanFactory beanFactory) { + return new TraceFeignObjectWrapper(beanFactory); + } + + @Bean + TraceFeignAspect traceFeignAspect(BeanFactory beanFactory) { + return new TraceFeignAspect(beanFactory); + } + @Configuration @ConditionalOnProperty(name = "spring.sleuth.feign.processor.enabled", matchIfMissing = true) protected static class FeignBeanPostProcessorConfiguration { - @Bean static FeignContextBeanPostProcessor feignContextBeanPostProcessor(BeanFactory beanFactory) { + @Bean + static FeignContextBeanPostProcessor feignContextBeanPostProcessor( + BeanFactory beanFactory) { return new FeignContextBeanPostProcessor(beanFactory); } + } @Configuration @ConditionalOnClass(OkHttpClient.class) protected static class OkHttpClientFeignBeanPostProcessorConfiguration { - @Bean static OkHttpFeignClientBeanPostProcessor okHttpFeignClientBeanPostProcessor(BeanFactory beanFactory) { + @Bean + static OkHttpFeignClientBeanPostProcessor okHttpFeignClientBeanPostProcessor( + BeanFactory beanFactory) { return new OkHttpFeignClientBeanPostProcessor(beanFactory); } + } - @Bean - TraceFeignObjectWrapper traceFeignObjectWrapper(BeanFactory beanFactory) { - return new TraceFeignObjectWrapper(beanFactory); - } - - @Bean TraceFeignAspect traceFeignAspect(BeanFactory beanFactory) { - return new TraceFeignAspect(beanFactory); - } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignContext.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignContext.java index 39261a1b3..d0eb6ace8 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignContext.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignContext.java @@ -22,8 +22,8 @@ import java.util.Map; import org.springframework.cloud.openfeign.FeignContext; /** - * Custom FeignContext that wraps beans in custom Feign configurations in their - * tracing representations. + * Custom FeignContext that wraps beans in custom Feign configurations in their tracing + * representations. * * @author Marcin Grzejszczak * @since 1.0.1 @@ -31,6 +31,7 @@ import org.springframework.cloud.openfeign.FeignContext; class TraceFeignContext extends FeignContext { private final TraceFeignObjectWrapper traceFeignObjectWrapper; + private final FeignContext delegate; TraceFeignContext(TraceFeignObjectWrapper traceFeignObjectWrapper, @@ -55,7 +56,8 @@ class TraceFeignContext extends FeignContext { } Map convertedInstances = new HashMap<>(); for (Map.Entry entry : instances.entrySet()) { - convertedInstances.put(entry.getKey(), (T) this.traceFeignObjectWrapper.wrap(entry.getValue())); + convertedInstances.put(entry.getKey(), + (T) this.traceFeignObjectWrapper.wrap(entry.getValue())); } return convertedInstances; } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignObjectWrapper.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignObjectWrapper.java index 7d4dab568..42644ce6f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignObjectWrapper.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignObjectWrapper.java @@ -18,9 +18,9 @@ package org.springframework.cloud.sleuth.instrument.web.client.feign; import feign.Client; import org.springframework.beans.factory.BeanFactory; +import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory; import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; -import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.util.ClassUtils; /** @@ -31,33 +31,37 @@ import org.springframework.util.ClassUtils; */ final class TraceFeignObjectWrapper { - private final BeanFactory beanFactory; - - private CachingSpringLoadBalancerFactory cachingSpringLoadBalancerFactory; - private Object springClientFactory; private static final boolean ribbonPresent; static { - ribbonPresent = - ClassUtils.isPresent("org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient", null) && - ClassUtils.isPresent("org.springframework.cloud.netflix.ribbon.SpringClientFactory", null); + ribbonPresent = ClassUtils.isPresent( + "org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient", + null) + && ClassUtils.isPresent( + "org.springframework.cloud.netflix.ribbon.SpringClientFactory", + null); } + private final BeanFactory beanFactory; + private CachingSpringLoadBalancerFactory cachingSpringLoadBalancerFactory; + private Object springClientFactory; + TraceFeignObjectWrapper(BeanFactory beanFactory) { this.beanFactory = beanFactory; } Object wrap(Object bean) { if (bean instanceof Client && !(bean instanceof TracingFeignClient)) { - if (ribbonPresent && - bean instanceof LoadBalancerFeignClient && !(bean instanceof TraceLoadBalancerFeignClient)) { + if (ribbonPresent && bean instanceof LoadBalancerFeignClient + && !(bean instanceof TraceLoadBalancerFeignClient)) { LoadBalancerFeignClient client = ((LoadBalancerFeignClient) bean); return new TraceLoadBalancerFeignClient( (Client) new TraceFeignObjectWrapper(this.beanFactory) .wrap(client.getDelegate()), - factory(), (SpringClientFactory) clientFactory(), this.beanFactory); - } else if (ribbonPresent && - bean instanceof TraceLoadBalancerFeignClient) { + factory(), (SpringClientFactory) clientFactory(), + this.beanFactory); + } + else if (ribbonPresent && bean instanceof TraceLoadBalancerFeignClient) { return bean; } return new LazyTracingFeignClient(this.beanFactory, (Client) bean); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceLoadBalancerFeignClient.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceLoadBalancerFeignClient.java index be1e15160..b9d28e215 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceLoadBalancerFeignClient.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceLoadBalancerFeignClient.java @@ -34,8 +34,8 @@ import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFacto import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient; /** - * We need to wrap the {@link LoadBalancerFeignClient} into a trace representation - * due to casts in {@link org.springframework.cloud.openfeign.FeignClientFactoryBean}. + * We need to wrap the {@link LoadBalancerFeignClient} into a trace representation due to + * casts in {@link org.springframework.cloud.openfeign.FeignClientFactoryBean}. * * @author Marcin Grzejszczak * @since 1.0.7 @@ -45,8 +45,11 @@ public class TraceLoadBalancerFeignClient extends LoadBalancerFeignClient { private static final Log log = LogFactory.getLog(TraceLoadBalancerFeignClient.class); private final BeanFactory beanFactory; + Tracer tracer; + HttpTracing httpTracing; + TracingFeignClient tracingFeignClient; public TraceLoadBalancerFeignClient(Client delegate, @@ -56,8 +59,8 @@ public class TraceLoadBalancerFeignClient extends LoadBalancerFeignClient { this.beanFactory = beanFactory; } - @Override public Response execute(Request request, Request.Options options) - throws IOException { + @Override + public Response execute(Request request, Request.Options options) throws IOException { if (log.isDebugEnabled()) { log.debug("Before send"); } @@ -69,21 +72,26 @@ public class TraceLoadBalancerFeignClient extends LoadBalancerFeignClient { log.debug("After receive"); } return response; - } catch (Exception e){ + } + catch (Exception e) { if (log.isDebugEnabled()) { log.debug("Exception thrown", e); } - if (e instanceof IOException || e.getCause() != null && - e.getCause() instanceof ClientException && - ((ClientException) e.getCause()).getErrorType() == ClientException.ErrorType.GENERAL ) { + if (e instanceof IOException || e.getCause() != null + && e.getCause() instanceof ClientException + && ((ClientException) e.getCause()) + .getErrorType() == ClientException.ErrorType.GENERAL) { if (log.isDebugEnabled()) { - log.debug("General exception was thrown, so most likely the traced client wasn't called. Falling back to a manual span"); + log.debug( + "General exception was thrown, so most likely the traced client wasn't called. Falling back to a manual span"); } - fallbackSpan = tracingFeignClient().handleSend(new HashMap<>(request.headers()), request, fallbackSpan); + fallbackSpan = tracingFeignClient().handleSend( + new HashMap<>(request.headers()), request, fallbackSpan); tracingFeignClient().handleReceive(fallbackSpan, response, e); } throw e; - } finally { + } + finally { fallbackSpan.abandon(); } } @@ -104,8 +112,8 @@ public class TraceLoadBalancerFeignClient extends LoadBalancerFeignClient { private TracingFeignClient tracingFeignClient() { if (this.tracingFeignClient == null) { - this.tracingFeignClient = - (TracingFeignClient) TracingFeignClient.create(httpTracing(), getDelegate()); + this.tracingFeignClient = (TracingFeignClient) TracingFeignClient + .create(httpTracing(), getDelegate()); } return this.tracingFeignClient; } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignClient.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignClient.java index c99573f26..0cf1e944f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignClient.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignClient.java @@ -45,31 +45,28 @@ final class TracingFeignClient implements Client { private static final Log log = LogFactory.getLog(TracingFeignClient.class); - static final Propagation.Setter>, String> SETTER = - new Propagation.Setter>, String>() { - @Override public void put(Map> carrier, String key, + static final Propagation.Setter>, String> SETTER = new Propagation.Setter>, String>() { + @Override + public void put(Map> carrier, String key, String value) { if (!carrier.containsKey(key)) { carrier.put(key, Collections.singletonList(value)); if (log.isTraceEnabled()) { log.trace("Added key [" + key + "] and header value [" + value + "]"); } - } else { + } + else { if (log.isTraceEnabled()) { log.trace("Key [" + key + "] already there in the headers"); } } } - @Override public String toString() { + @Override + public String toString() { return "Map::set"; } }; - - static Client create(HttpTracing httpTracing, Client delegate) { - return new TracingFeignClient(httpTracing, delegate); - } - final Tracer tracer; final Client delegate; final HttpClientHandler handler; @@ -82,8 +79,12 @@ final class TracingFeignClient implements Client { this.delegate = delegate; } - @Override public Response execute(Request request, Request.Options options) - throws IOException { + static Client create(HttpTracing httpTracing, Client delegate) { + return new TracingFeignClient(httpTracing, delegate); + } + + @Override + public Response execute(Request request, Request.Options options) throws IOException { Map> headers = new HashMap<>(request.headers()); Span span = handleSend(headers, request, null); if (log.isDebugEnabled()) { @@ -92,7 +93,8 @@ final class TracingFeignClient implements Client { Response response = null; Throwable error = null; try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { - return response = this.delegate.execute(modifiedRequest(request, headers), options); + return response = this.delegate.execute(modifiedRequest(request, headers), + options); } catch (IOException | RuntimeException | Error e) { error = e; @@ -106,7 +108,8 @@ final class TracingFeignClient implements Client { } } - Span handleSend(Map> headers, Request request, Span clientSpan) { + Span handleSend(Map> headers, Request request, + Span clientSpan) { if (clientSpan != null) { return this.handler.handleSend(this.injector, headers, request, clientSpan); } @@ -117,7 +120,8 @@ final class TracingFeignClient implements Client { this.handler.handleReceive(response, error, span); } - private Request modifiedRequest(Request request, Map> headers) { + private Request modifiedRequest(Request request, + Map> headers) { String method = request.method(); String url = request.url(); byte[] body = request.body(); @@ -128,23 +132,28 @@ final class TracingFeignClient implements Client { static final class HttpAdapter extends brave.http.HttpClientAdapter { - @Override public String method(Request request) { + @Override + public String method(Request request) { return request.method(); } - @Override public String url(Request request) { + @Override + public String url(Request request) { return request.url(); } - @Override public String requestHeader(Request request, String name) { + @Override + public String requestHeader(Request request, String name) { Collection result = request.headers().get(name); - return result != null && result.iterator().hasNext() ? - result.iterator().next() : - null; + return result != null && result.iterator().hasNext() + ? result.iterator().next() : null; } - @Override public Integer statusCode(Response response) { + @Override + public Integer statusCode(Response response) { return response.status(); } + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilter.java index f42c0de5c..545067a7a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilter.java @@ -40,11 +40,11 @@ class TracePostZuulFilter extends ZuulFilter { private static final Log log = LogFactory.getLog(TracePostZuulFilter.class); private final HttpServerHandler handler; + private final Tracer tracer; TracePostZuulFilter(HttpTracing httpTracing) { - this.handler = HttpServerHandler.create(httpTracing, - new HttpServletAdapter()); + this.handler = HttpServerHandler.create(httpTracing, new HttpServletAdapter()); this.tracer = httpTracing.tracing().tracer(); } @@ -57,8 +57,10 @@ class TracePostZuulFilter extends ZuulFilter { if (response.getStatus() == 0) { return false; } - HttpStatus.Series httpStatusSeries = HttpStatus.Series.valueOf(response.getStatus()); - return httpStatusSeries == HttpStatus.Series.SUCCESSFUL || httpStatusSeries == HttpStatus.Series.REDIRECTION; + HttpStatus.Series httpStatusSeries = HttpStatus.Series + .valueOf(response.getStatus()); + return httpStatusSeries == HttpStatus.Series.SUCCESSFUL + || httpStatusSeries == HttpStatus.Series.REDIRECTION; } @Override diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java index 65c75d21e..86736c3ee 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java @@ -28,8 +28,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * enables span information propagation when using Zuul. + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} enables span information propagation when using Zuul. * * @author Dave Syer * @since 1.0.0 @@ -42,14 +42,15 @@ import org.springframework.context.annotation.Configuration; @AutoConfigureAfter(TraceWebServletAutoConfiguration.class) public class TraceZuulAutoConfiguration { + @Bean + static TraceZuulHandlerMappingBeanPostProcessor traceHandlerMappingBeanPostProcessor( + BeanFactory beanFactory) { + return new TraceZuulHandlerMappingBeanPostProcessor(beanFactory); + } + @Bean TracePostZuulFilter tracePostZuulFilter(HttpTracing httpTracing) { return new TracePostZuulFilter(httpTracing); } - @Bean - static TraceZuulHandlerMappingBeanPostProcessor traceHandlerMappingBeanPostProcessor(BeanFactory beanFactory) { - return new TraceZuulHandlerMappingBeanPostProcessor(beanFactory); - } - } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulHandlerMappingBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulHandlerMappingBeanPostProcessor.java index 7aa53fa71..7f9a5d4bd 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulHandlerMappingBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulHandlerMappingBeanPostProcessor.java @@ -27,15 +27,15 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping; /** - * Bean post processor that wraps {@link ZuulHandlerMapping} in its - * trace representation. + * Bean post processor that wraps {@link ZuulHandlerMapping} in its trace representation. * * @author Marcin Grzejszczak * @since 1.0.3 */ class TraceZuulHandlerMappingBeanPostProcessor implements BeanPostProcessor { - private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + private static final Log log = LogFactory + .getLog(MethodHandles.lookup().lookupClass()); private final BeanFactory beanFactory; @@ -54,12 +54,14 @@ class TraceZuulHandlerMappingBeanPostProcessor implements BeanPostProcessor { throws BeansException { if (bean instanceof ZuulHandlerMapping) { if (log.isDebugEnabled()) { - log.debug("Attaching trace interceptor to bean [" + beanName + "] of type [" + bean.getClass().getSimpleName() + "]"); + log.debug("Attaching trace interceptor to bean [" + beanName + + "] of type [" + bean.getClass().getSimpleName() + "]"); } ZuulHandlerMapping zuulHandlerMapping = (ZuulHandlerMapping) bean; - zuulHandlerMapping.setInterceptors( - this.beanFactory.getBean(SpanCustomizingAsyncHandlerInterceptor.class)); + zuulHandlerMapping.setInterceptors(this.beanFactory + .getBean(SpanCustomizingAsyncHandlerInterceptor.class)); } return bean; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java index b731adcf6..258c39a8a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java @@ -28,8 +28,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * enables a {@link Slf4jCurrentTraceContext} that prints tracing information in the logs. + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} enables a {@link Slf4jCurrentTraceContext} that prints tracing + * information in the logs. *

    * * @author Spencer Gibb @@ -37,10 +38,13 @@ import org.springframework.context.annotation.Configuration; * @since 2.0.0 */ @Configuration -@ConditionalOnProperty(value="spring.sleuth.enabled", matchIfMissing=true) +@ConditionalOnProperty(value = "spring.sleuth.enabled", matchIfMissing = true) @AutoConfigureBefore(TraceAutoConfiguration.class) public class SleuthLogAutoConfiguration { + /** + * Configuration for Slfj4 + */ @Configuration @ConditionalOnClass(MDC.class) @EnableConfigurationProperties(SleuthSlf4jProperties.class) @@ -48,9 +52,12 @@ public class SleuthLogAutoConfiguration { @Bean @ConditionalOnProperty(value = "spring.sleuth.log.slf4j.enabled", matchIfMissing = true) - public CurrentTraceContext.ScopeDecorator slf4jSpanDecorator(SleuthProperties sleuthProperties, + public CurrentTraceContext.ScopeDecorator slf4jSpanDecorator( + SleuthProperties sleuthProperties, SleuthSlf4jProperties sleuthSlf4jProperties) { return new Slf4jScopeDecorator(sleuthProperties, sleuthSlf4jProperties); } + } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthSlf4jProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthSlf4jProperties.java index 6eb114c9c..b4eccab3c 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthSlf4jProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthSlf4jProperties.java @@ -22,7 +22,7 @@ import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Configuration properties for slf4j + * Configuration properties for slf4j. * * @author Arthur Gavlyukovskiy * @since 1.0.12 @@ -36,7 +36,7 @@ public class SleuthSlf4jProperties { private boolean enabled = true; /** - * A list of keys to be put from baggage to MDC + * A list of keys to be put from baggage to MDC. */ private List whitelistedMdcKeys = new ArrayList<>(); @@ -55,4 +55,5 @@ public class SleuthSlf4jProperties { public void setWhitelistedMdcKeys(List whitelistedMdcKeys) { this.whitelistedMdcKeys = whitelistedMdcKeys; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jCurrentTraceContext.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jCurrentTraceContext.java index bbc70dba8..a069544c1 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jCurrentTraceContext.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jCurrentTraceContext.java @@ -25,17 +25,17 @@ import org.slf4j.LoggerFactory; import org.slf4j.MDC; /** - * Adds {@linkplain org.slf4j.MDC} properties "traceId", "parentId", "spanId" and "spanExportable" when a {@link - * brave.Tracer#currentSpan() span is current}. These can be used in log correlation. - * Supports backward compatibility of MDC entries by adding legacy "X-B3" entries to MDC context - * "X-B3-TraceId", "X-B3-ParentSpanId", "X-B3-SpanId" and "X-B3-Sampled" + * Adds {@linkplain org.slf4j.MDC} properties "traceId", "parentId", "spanId" and + * "spanExportable" when a {@link brave.Tracer#currentSpan() span is current}. These can + * be used in log correlation. Supports backward compatibility of MDC entries by adding + * legacy "X-B3" entries to MDC context "X-B3-TraceId", "X-B3-ParentSpanId", "X-B3-SpanId" + * and "X-B3-Sampled" * - * Due to the migration to {@link brave.propagation.CurrentTraceContext.ScopeDecorator} approach, - * we are making the default implementation package scope since you can register your - * own implementation of the Scope Decorator. + * Due to the migration to {@link brave.propagation.CurrentTraceContext.ScopeDecorator} + * approach, we are making the default implementation package scope since you can register + * your own implementation of the Scope Decorator. * * @author Marcin Grzejszczak - * * @since 2.0.0 * @deprecated {@link Slf4jScopeDecorator} will be used */ @@ -44,8 +44,11 @@ public final class Slf4jCurrentTraceContext extends CurrentTraceContext { // Backward compatibility for all logging patterns private static final String LEGACY_EXPORTABLE_NAME = "X-Span-Export"; + private static final String LEGACY_PARENT_ID_NAME = "X-B3-ParentSpanId"; + private static final String LEGACY_TRACE_ID_NAME = "X-B3-TraceId"; + private static final String LEGACY_SPAN_ID_NAME = "X-B3-SpanId"; private static final Logger log = LoggerFactory @@ -62,16 +65,19 @@ public final class Slf4jCurrentTraceContext extends CurrentTraceContext { final CurrentTraceContext delegate; Slf4jCurrentTraceContext(CurrentTraceContext delegate) { - if (delegate == null) + if (delegate == null) { throw new NullPointerException("delegate == null"); + } this.delegate = delegate; } - @Override public TraceContext get() { + @Override + public TraceContext get() { return this.delegate.get(); } - @Override public Scope newScope(@Nullable TraceContext currentSpan) { + @Override + public Scope newScope(@Nullable TraceContext currentSpan) { final String previousTraceId = MDC.get("traceId"); final String previousParentId = MDC.get("parentId"); final String previousSpanId = MDC.get("spanId"); @@ -85,9 +91,8 @@ public final class Slf4jCurrentTraceContext extends CurrentTraceContext { String traceIdString = currentSpan.traceIdString(); MDC.put("traceId", traceIdString); MDC.put(LEGACY_TRACE_ID_NAME, traceIdString); - String parentId = currentSpan.parentId() != null ? - HexCodec.toLowerHex(currentSpan.parentId()) : - null; + String parentId = currentSpan.parentId() != null + ? HexCodec.toLowerHex(currentSpan.parentId()) : null; replace("parentId", parentId); replace(LEGACY_PARENT_ID_NAME, parentId); String spanId = HexCodec.toLowerHex(currentSpan.spanId()); @@ -116,8 +121,14 @@ public final class Slf4jCurrentTraceContext extends CurrentTraceContext { Scope scope = this.delegate.newScope(currentSpan); + /** + * Thread context scope. + * @author Adrian Cole + */ class ThreadContextCurrentTraceContextScope implements Scope { - @Override public void close() { + + @Override + public void close() { log("Closing scope for span: {}", currentSpan); scope.close(); replace("traceId", previousTraceId); @@ -129,6 +140,7 @@ public final class Slf4jCurrentTraceContext extends CurrentTraceContext { replace(LEGACY_SPAN_ID_NAME, legacyPreviousSpanId); replace(LEGACY_EXPORTABLE_NAME, legacySpanExportable); } + } return new ThreadContextCurrentTraceContextScope(); } @@ -150,4 +162,5 @@ public final class Slf4jCurrentTraceContext extends CurrentTraceContext { MDC.remove(key); } } -} \ No newline at end of file + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jScopeDecorator.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jScopeDecorator.java index 3f1ce318e..b6b935379 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jScopeDecorator.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jScopeDecorator.java @@ -33,34 +33,40 @@ import org.springframework.cloud.sleuth.autoconfig.SleuthProperties; import org.springframework.util.StringUtils; /** - * Adds {@linkplain MDC} properties "traceId", "parentId", "spanId" and "spanExportable" when a {@link - * brave.Tracer#currentSpan() span is current}. These can be used in log correlation. - * Supports backward compatibility of MDC entries by adding legacy "X-B3" entries to MDC context - * "X-B3-TraceId", "X-B3-ParentSpanId", "X-B3-SpanId" and "X-B3-Sampled" + * Adds {@linkplain MDC} properties "traceId", "parentId", "spanId" and "spanExportable" + * when a {@link brave.Tracer#currentSpan() span is current}. These can be used in log + * correlation. Supports backward compatibility of MDC entries by adding legacy "X-B3" + * entries to MDC context "X-B3-TraceId", "X-B3-ParentSpanId", "X-B3-SpanId" and + * "X-B3-Sampled" * * @author Marcin Grzejszczak - * * @since 2.1.0 */ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator { // Backward compatibility for all logging patterns private static final String LEGACY_EXPORTABLE_NAME = "X-Span-Export"; + private static final String LEGACY_PARENT_ID_NAME = "X-B3-ParentSpanId"; + private static final String LEGACY_TRACE_ID_NAME = "X-B3-TraceId"; + private static final String LEGACY_SPAN_ID_NAME = "X-B3-SpanId"; private static final Logger log = LoggerFactory.getLogger(Slf4jScopeDecorator.class); private final SleuthProperties sleuthProperties; + private final SleuthSlf4jProperties sleuthSlf4jProperties; - Slf4jScopeDecorator(SleuthProperties sleuthProperties, SleuthSlf4jProperties sleuthSlf4jProperties) { + Slf4jScopeDecorator(SleuthProperties sleuthProperties, + SleuthSlf4jProperties sleuthSlf4jProperties) { this.sleuthProperties = sleuthProperties; this.sleuthSlf4jProperties = sleuthSlf4jProperties; } - @Override public CurrentTraceContext.Scope decorateScope(TraceContext currentSpan, + @Override + public CurrentTraceContext.Scope decorateScope(TraceContext currentSpan, CurrentTraceContext.Scope scope) { final String previousTraceId = MDC.get("traceId"); final String previousParentId = MDC.get("parentId"); @@ -70,18 +76,16 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator { final String legacyPreviousParentId = MDC.get(LEGACY_PARENT_ID_NAME); final String legacyPreviousSpanId = MDC.get(LEGACY_SPAN_ID_NAME); final String legacySpanExportable = MDC.get(LEGACY_EXPORTABLE_NAME); - final List> previousMdc = - whitelistedBaggageKeys(currentSpan) - .map(s -> new AbstractMap.SimpleEntry<>(s, MDC.get(s))) - .collect(Collectors.toList()); + final List> previousMdc = whitelistedBaggageKeys( + currentSpan).map((s) -> new AbstractMap.SimpleEntry<>(s, MDC.get(s))) + .collect(Collectors.toList()); if (currentSpan != null) { String traceIdString = currentSpan.traceIdString(); MDC.put("traceId", traceIdString); MDC.put(LEGACY_TRACE_ID_NAME, traceIdString); - String parentId = currentSpan.parentId() != null ? - HexCodec.toLowerHex(currentSpan.parentId()) : - null; + String parentId = currentSpan.parentId() != null + ? HexCodec.toLowerHex(currentSpan.parentId()) : null; replace("parentId", parentId); replace(LEGACY_PARENT_ID_NAME, parentId); String spanId = HexCodec.toLowerHex(currentSpan.spanId()); @@ -97,7 +101,7 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator { } } whitelistedBaggageKeys(currentSpan) - .forEach(s -> MDC.put(s, ExtraFieldPropagation.get(currentSpan, s))); + .forEach((s) -> MDC.put(s, ExtraFieldPropagation.get(currentSpan, s))); } else { MDC.remove("traceId"); @@ -111,8 +115,14 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator { whitelistedBaggageKeys(currentSpan).forEach(MDC::remove); } + /** + * Thread context scope. + * @author Adrian Cole + */ class ThreadContextCurrentTraceContextScope implements CurrentTraceContext.Scope { - @Override public void close() { + + @Override + public void close() { log("Closing scope for span: {}", currentSpan); scope.close(); replace("traceId", previousTraceId); @@ -123,16 +133,18 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator { replace(LEGACY_PARENT_ID_NAME, legacyPreviousParentId); replace(LEGACY_SPAN_ID_NAME, legacyPreviousSpanId); replace(LEGACY_EXPORTABLE_NAME, legacySpanExportable); - previousMdc.forEach(e -> replace(e.getKey(), e.getValue())); + previousMdc.forEach((e) -> replace(e.getKey(), e.getValue())); } + } return new ThreadContextCurrentTraceContextScope(); } private Stream whitelistedBaggageKeys(TraceContext context) { - return this.sleuthProperties.getBaggageKeys().stream() - .filter(s -> this.sleuthSlf4jProperties.getWhitelistedMdcKeys().contains(s) && - context != null && StringUtils.hasText(ExtraFieldPropagation.get(context, s))); + return this.sleuthProperties.getBaggageKeys().stream().filter( + (s) -> this.sleuthSlf4jProperties.getWhitelistedMdcKeys().contains(s) + && context != null + && StringUtils.hasText(ExtraFieldPropagation.get(context, s))); } private void log(String text, TraceContext span) { @@ -152,4 +164,5 @@ final class Slf4jScopeDecorator implements CurrentTraceContext.ScopeDecorator { MDC.remove(key); } } -} \ No newline at end of file + +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/ProbabilityBasedSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/ProbabilityBasedSampler.java index e63c7421c..48dd687d1 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/ProbabilityBasedSampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/ProbabilityBasedSampler.java @@ -23,15 +23,21 @@ import java.util.concurrent.atomic.AtomicInteger; import brave.sampler.Sampler; /** - * This sampler is appropriate for low-traffic instrumentation (ex servers that each receive <100K - * requests), or those who do not provision random trace ids. It not appropriate for collectors as - * the sampling decision isn't idempotent (consistent based on trace id). + * This sampler is appropriate for low-traffic instrumentation (ex servers that each + * receive <100K requests), or those who do not provision random trace ids. It not + * appropriate for collectors as the sampling decision isn't idempotent (consistent based + * on trace id). * *

    Implementation

    * - *

    Taken from Zipkin project

    + *

    + * Taken from Zipkin + * project + *

    * - *

    This counts to see how many out of 100 traces should be retained. This means that it is + *

    + * This counts to see how many out of 100 traces should be retained. This means that it is * accurate in units of 100 traces. * * @author Marcin Grzejszczak @@ -41,7 +47,9 @@ import brave.sampler.Sampler; public class ProbabilityBasedSampler extends Sampler { private final AtomicInteger counter = new AtomicInteger(0); + private final BitSet sampleDecisions; + private final SamplerProperties configuration; public ProbabilityBasedSampler(SamplerProperties configuration) { @@ -54,7 +62,8 @@ public class ProbabilityBasedSampler extends Sampler { public boolean isSampled(long traceId) { if (this.configuration.getProbability() == 0) { return false; - } else if (this.configuration.getProbability() == 1.0f) { + } + else if (this.configuration.getProbability() == 1.0f) { return true; } synchronized (this) { @@ -71,6 +80,11 @@ public class ProbabilityBasedSampler extends Sampler { * Reservoir sampling algorithm borrowed from Stack Overflow. * * http://stackoverflow.com/questions/12817946/generate-a-random-bitset-with-n-1s + * + * @param size + * @param cardinality + * @param rnd + * @return a random bitset */ static BitSet randomBitSet(int size, int cardinality, Random rnd) { BitSet result = new BitSet(size); @@ -90,4 +104,5 @@ public class ProbabilityBasedSampler extends Sampler { } return result; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerProperties.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerProperties.java index 2e1701a3e..4af7f075c 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerProperties.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerProperties.java @@ -19,7 +19,7 @@ package org.springframework.cloud.sleuth.sampler; import org.springframework.boot.context.properties.ConfigurationProperties; /** - * Properties related to sampling + * Properties related to sampling. * * @author Marcin Grzejszczak * @author Adrian Cole @@ -42,4 +42,5 @@ public class SamplerProperties { public void setProbability(float probability) { this.probability = probability; } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/util/ArrayListSpanReporter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/util/ArrayListSpanReporter.java index 9648d50cb..7b3d0e117 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/util/ArrayListSpanReporter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/util/ArrayListSpanReporter.java @@ -29,6 +29,7 @@ import zipkin2.reporter.Reporter; * @since 2.0.0 */ public class ArrayListSpanReporter implements Reporter { + private final List spans = new ArrayList<>(); public List getSpans() { @@ -39,9 +40,7 @@ public class ArrayListSpanReporter implements Reporter { @Override public String toString() { - return "ArrayListSpanAccumulator{" + - "spans=" + getSpans() + - '}'; + return "ArrayListSpanAccumulator{" + "spans=" + getSpans() + '}'; } @Override @@ -56,4 +55,5 @@ public class ArrayListSpanReporter implements Reporter { this.spans.clear(); } } + } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/util/SpanNameUtil.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/util/SpanNameUtil.java index 9883ae722..263620e38 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/util/SpanNameUtil.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/util/SpanNameUtil.java @@ -19,7 +19,7 @@ package org.springframework.cloud.sleuth.util; import org.springframework.util.StringUtils; /** - * Utility class that provides the name in hyphen based notation + * Utility class that provides the name in hyphen based notation. * * @author Adrian Cole * @since 1.0.2 @@ -28,11 +28,15 @@ public final class SpanNameUtil { static final int MAX_NAME_LENGTH = 50; + private SpanNameUtil() { + + } + public static String shorten(String name) { if (StringUtils.isEmpty(name)) { return name; } - int maxLength = name.length() > MAX_NAME_LENGTH ? MAX_NAME_LENGTH : name.length(); + int maxLength = name.length() > MAX_NAME_LENGTH ? (MAX_NAME_LENGTH) : (name.length()); return name.substring(0, maxLength); } @@ -41,12 +45,16 @@ public final class SpanNameUtil { for (int i = 0; i < name.length(); i++) { char c = name.charAt(i); if (Character.isUpperCase(c)) { - if (i != 0) result.append('-'); + if (i != 0) { + result.append('-'); + } result.append(Character.toLowerCase(c)); - } else { + } + else { result.append(c); } } return SpanNameUtil.shorten(result.toString()); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DisableSecurity.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DisableSecurity.java index bd3f5bb03..59dc47460 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DisableSecurity.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DisableSecurity.java @@ -28,8 +28,9 @@ import org.springframework.context.annotation.Import; * @author Marcin Grzejszczak */ @Import(PermitAllServletConfiguration.class) -@Target({ ElementType.TYPE}) +@Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DisableSecurity { + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DisableWebFluxSecurity.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DisableWebFluxSecurity.java index 254ce3179..fd3d579d8 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DisableWebFluxSecurity.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DisableWebFluxSecurity.java @@ -28,8 +28,9 @@ import org.springframework.context.annotation.Import; * @author Marcin Grzejszczak */ @Import(PermitAllWebFluxSecurityConfiguration.class) -@Target({ ElementType.TYPE}) +@Target({ ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DisableWebFluxSecurity { + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/FinishedSpanHandlerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/FinishedSpanHandlerTests.java index 757daba00..417bbf8a6 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/FinishedSpanHandlerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/FinishedSpanHandlerTests.java @@ -39,12 +39,14 @@ import zipkin2.reporter.Reporter; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = FinishedSpanHandlerTests.FinishedSpanHandlerAspectTestsConfig.class, - webEnvironment = SpringBootTest.WebEnvironment.NONE) +@SpringBootTest(classes = FinishedSpanHandlerTests.FinishedSpanHandlerAspectTestsConfig.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) public class FinishedSpanHandlerTests { - @Autowired ArrayListSpanReporter reporter; - @Autowired Tracer tracer; + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + Tracer tracer; @Test public void should_adjust_span_twice_before_reporting() { @@ -59,32 +61,41 @@ public class FinishedSpanHandlerTests { @Configuration @EnableAutoConfiguration(exclude = IntegrationAutoConfiguration.class) static class FinishedSpanHandlerAspectTestsConfig { - @Bean Sampler sampler() { + + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean Reporter reporter() { + @Bean + Reporter reporter() { return new ArrayListSpanReporter(); } // tag::finishedSpanHandler[] - @Bean FinishedSpanHandler handlerOne() { + @Bean + FinishedSpanHandler handlerOne() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name("foo"); return true; // keep this span } }; } - @Bean FinishedSpanHandler handlerTwo() { + @Bean + FinishedSpanHandler handlerTwo() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name(span.name() + " bar"); return true; // keep this span } }; } // end::finishedSpanHandler[] + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/PermitAllServletConfiguration.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/PermitAllServletConfiguration.java index b64004bf5..d395bce77 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/PermitAllServletConfiguration.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/PermitAllServletConfiguration.java @@ -26,10 +26,10 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur @EnableWebSecurity @Order(99) public class PermitAllServletConfiguration extends WebSecurityConfigurerAdapter { + @Override protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests() - .antMatchers("/*").permitAll(); + http.authorizeRequests().antMatchers("/*").permitAll(); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/PermitAllWebFluxSecurityConfiguration.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/PermitAllWebFluxSecurityConfiguration.java index 521b382d0..0c4e8b10c 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/PermitAllWebFluxSecurityConfiguration.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/PermitAllWebFluxSecurityConfiguration.java @@ -23,11 +23,12 @@ import org.springframework.security.web.server.SecurityWebFilterChain; @Configuration public class PermitAllWebFluxSecurityConfiguration { - @Bean SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception { - return http.authorizeExchange() - .anyExchange().permitAll() - .and() - .csrf().disable() + + @Bean + SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) + throws Exception { + return http.authorizeExchange().anyExchange().permitAll().and().csrf().disable() .build(); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SleuthTestAutoConfiguration.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SleuthTestAutoConfiguration.java index f74ec89d7..f6125e883 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SleuthTestAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SleuthTestAutoConfiguration.java @@ -29,18 +29,23 @@ public class SleuthTestAutoConfiguration { @Configuration @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE) static class ReactiveConfiguration { + @Import(PermitAllWebFluxSecurityConfiguration.class) static class ImportConfiguration { } + } @Configuration @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) static class ServletConfiguration { + @Import(PermitAllServletConfiguration.class) static class ImportConfiguration { } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanAdjusterTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanAdjusterTests.java index 3674dc668..e1ad49ede 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanAdjusterTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanAdjusterTests.java @@ -36,12 +36,14 @@ import zipkin2.reporter.Reporter; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = SpanAdjusterTests.SpanAdjusterAspectTestsConfig.class, - webEnvironment = SpringBootTest.WebEnvironment.NONE) +@SpringBootTest(classes = SpanAdjusterTests.SpanAdjusterAspectTestsConfig.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) public class SpanAdjusterTests { - @Autowired ArrayListSpanReporter reporter; - @Autowired Tracer tracer; + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + Tracer tracer; @Test public void should_adjust_span_twice_before_reporting() { @@ -56,22 +58,29 @@ public class SpanAdjusterTests { @Configuration @EnableAutoConfiguration(exclude = IntegrationAutoConfiguration.class) static class SpanAdjusterAspectTestsConfig { - @Bean Sampler sampler() { + + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean Reporter reporter() { + @Bean + Reporter reporter() { return new ArrayListSpanReporter(); } // tag::adjuster[] - @Bean SpanAdjuster adjusterOne() { + @Bean + SpanAdjuster adjusterOne() { return span -> span.toBuilder().name("foo").build(); } - @Bean SpanAdjuster adjusterTwo() { + @Bean + SpanAdjuster adjusterTwo() { return span -> span.toBuilder().name(span.name() + " bar").build(); } // end::adjuster[] + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/NoOpTagValueResolverTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/NoOpTagValueResolverTests.java index 687070d3d..aa7dd19f6 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/NoOpTagValueResolverTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/NoOpTagValueResolverTests.java @@ -24,7 +24,9 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ public class NoOpTagValueResolverTests { - @Test public void should_return_null() throws Exception { + + @Test + public void should_return_null() throws Exception { then(new NoOpTagValueResolver().resolve("")).isNull(); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthNewSpanParserAnnotationDisableTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthNewSpanParserAnnotationDisableTests.java index dff55c6d8..d49986b67 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthNewSpanParserAnnotationDisableTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthNewSpanParserAnnotationDisableTests.java @@ -25,14 +25,15 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) -@SpringBootTest(classes = SleuthAnnotationAutoConfiguration.class, - properties = "spring.sleuth.annotation.enabled=false") +@SpringBootTest(classes = SleuthAnnotationAutoConfiguration.class, properties = "spring.sleuth.annotation.enabled=false") public class SleuthNewSpanParserAnnotationDisableTests { - @Autowired(required = false) NewSpanParser newSpanParser; - + @Autowired(required = false) + NewSpanParser newSpanParser; + @Test public void shouldNotAutowireBecauseConfigIsDisabled() { assertThat(this.newSpanParser).isNull(); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthNewSpanParserAnnotationNoSleuthTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthNewSpanParserAnnotationNoSleuthTests.java index dc7f4204a..33ae0d816 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthNewSpanParserAnnotationNoSleuthTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthNewSpanParserAnnotationNoSleuthTests.java @@ -26,16 +26,19 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) -@SpringBootTest(classes = SleuthAnnotationAutoConfiguration.class, - properties = "spring.sleuth.enabled=false") +@SpringBootTest(classes = SleuthAnnotationAutoConfiguration.class, properties = "spring.sleuth.enabled=false") public class SleuthNewSpanParserAnnotationNoSleuthTests { - @Autowired(required = false) NewSpanParser newSpanParser; - @Autowired(required = false) Tracing tracing; + @Autowired(required = false) + NewSpanParser newSpanParser; + + @Autowired(required = false) + Tracing tracing; @Test public void shouldNotAutowireBecauseConfigIsDisabled() { assertThat(this.newSpanParser).isNull(); assertThat(this.tracing).isNull(); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectFluxTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectFluxTests.java index b57aad544..ea1316799 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectFluxTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectFluxTests.java @@ -49,17 +49,22 @@ import static org.springframework.cloud.sleuth.annotation.SleuthSpanCreatorAspec @SpringBootTest(classes = SleuthSpanCreatorAspectFluxTests.TestConfiguration.class) @RunWith(SpringJUnit4ClassRunner.class) public class SleuthSpanCreatorAspectFluxTests { - - @Autowired TestBeanInterface testBean; - @Autowired Tracer tracer; - @Autowired ArrayListSpanReporter reporter; - + + @Autowired + TestBeanInterface testBean; + + @Autowired + Tracer tracer; + + @Autowired + ArrayListSpanReporter reporter; + @Before public void setup() { this.reporter.clear(); testBean.reset(); } - + @Test public void shouldCreateSpanWhenAnnotationOnInterfaceMethod() { Flux flux = this.testBean.testMethod(); @@ -85,7 +90,7 @@ public class SleuthSpanCreatorAspectFluxTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWithCustomNameWhenAnnotationOnClassMethod() { Flux flux = this.testBean.testMethod3(); @@ -164,8 +169,7 @@ public class SleuthSpanCreatorAspectFluxTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("custom-name-on-test-method9"); - then(spans.get(0).tags()) - .containsEntry("class", "TestBean") + then(spans.get(0).tags()).containsEntry("class", "TestBean") .containsEntry("method", "testMethod9"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); @@ -179,18 +183,18 @@ public class SleuthSpanCreatorAspectFluxTests { Flux flux = this.testBean.testMethod10("test"); verifyNoSpansUntilFluxComplete(flux); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("customTestTag10", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).tags()).containsEntry("customTestTag10", "test"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -203,11 +207,10 @@ public class SleuthSpanCreatorAspectFluxTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("test-method10"); - then(spans.get(0).tags()) - .containsEntry("customTestTag10", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).tags()).containsEntry("customTestTag10", "test"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -220,18 +223,18 @@ public class SleuthSpanCreatorAspectFluxTests { Flux flux = this.testBean.testMethod10_v2("test"); verifyNoSpansUntilFluxComplete(flux); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("customTestTag10", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).tags()).containsEntry("customTestTag10", "test"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -245,20 +248,20 @@ public class SleuthSpanCreatorAspectFluxTests { Flux flux = this.testBean.testMethod11("test"); // end::continue_span_execution[] verifyNoSpansUntilFluxComplete(flux); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("class", "TestBean") + then(spans.get(0).tags()).containsEntry("class", "TestBean") .containsEntry("method", "testMethod11") .containsEntry("customTestTag11", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -271,14 +274,14 @@ public class SleuthSpanCreatorAspectFluxTests { then(this.reporter.getSpans()).isEmpty(); flux.toIterable().iterator().next(); - } catch (RuntimeException ignored) { + } + catch (RuntimeException ignored) { } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("test-method12"); - then(spans.get(0).tags()) - .containsEntry("testTag12", "test") + then(spans.get(0).tags()).containsEntry("testTag12", "test") .containsEntry("error", "test exception 12"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); @@ -296,20 +299,20 @@ public class SleuthSpanCreatorAspectFluxTests { flux.toIterable().iterator().next(); // end::continue_span_execution[] - } catch (RuntimeException ignored) { - } finally { + } + catch (RuntimeException ignored) { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("error", "test exception 13"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("testMethod13.before", "testMethod13.afterFailure", - "testMethod13.after"); + then(spans.get(0).tags()).containsEntry("error", "test exception 13"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("testMethod13.before", + "testMethod13.afterFailure", "testMethod13.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -348,7 +351,7 @@ public class SleuthSpanCreatorAspectFluxTests { then(this.tracer.currentSpan()).isNull(); } - private static String toHexString(long value){ + private static String toHexString(long value) { return StringUtils.leftPad(Long.toHexString(value), 16, '0'); } @@ -429,18 +432,22 @@ public class SleuthSpanCreatorAspectFluxTests { void proceed(); void reset(); + } - + protected static class TestBean implements TestBeanInterface { public static final String TEST_STRING1 = "Test String 1"; + public static final String TEST_STRING2 = "Test String 2"; private final Tracer tracer; - private AtomicReference> proceed - = new AtomicReference<>(new CompletableFuture<>()); - private Flux testFlux = Flux.defer(() -> Flux.just(TEST_STRING1, TEST_STRING2)) + private AtomicReference> proceed = new AtomicReference<>( + new CompletableFuture<>()); + + private Flux testFlux = Flux + .defer(() -> Flux.just(TEST_STRING1, TEST_STRING2)) .delayUntil(s -> Mono.fromFuture(proceed.get())) .doOnNext(s -> proceed.set(new CompletableFuture<>())); @@ -449,11 +456,11 @@ public class SleuthSpanCreatorAspectFluxTests { } @Override - public void reset(){ + public void reset() { proceed.set(new CompletableFuture<>()); } - public void proceed(){ + public void proceed() { proceed.get().complete(null); } @@ -480,7 +487,7 @@ public class SleuthSpanCreatorAspectFluxTests { public Flux testMethod4() { return testFlux; } - + @Override public Flux testMethod5(String test) { return testFlux; @@ -509,12 +516,14 @@ public class SleuthSpanCreatorAspectFluxTests { } @Override - public Flux testMethod10(@SpanTag(value = "customTestTag10") String param) { + public Flux testMethod10( + @SpanTag(value = "customTestTag10") String param) { return testFlux; } @Override - public Flux testMethod10_v2(@SpanTag(key = "customTestTag10") String param) { + public Flux testMethod10_v2( + @SpanTag(key = "customTestTag10") String param) { return testFlux; } @@ -526,12 +535,14 @@ public class SleuthSpanCreatorAspectFluxTests { @Override public Flux testMethod12(String param) { - return Flux.defer(() -> Flux.error(new RuntimeException("test exception 12"))); + return Flux + .defer(() -> Flux.error(new RuntimeException("test exception 12"))); } @Override public Flux testMethod13() { - return Flux.defer(() -> Flux.error(new RuntimeException("test exception 13"))); + return Flux + .defer(() -> Flux.error(new RuntimeException("test exception 13"))); } @Override @@ -546,11 +557,12 @@ public class SleuthSpanCreatorAspectFluxTests { @Override public Flux newSpanInSubscriberContext() { - return Mono.subscriberContext() - .flatMapMany(context -> Flux.just(tracer.currentSpan().context().spanId())); + return Mono.subscriberContext().flatMapMany( + context -> Flux.just(tracer.currentSpan().context().spanId())); } + } - + @Configuration @EnableAutoConfiguration protected static class TestConfiguration { @@ -560,12 +572,16 @@ public class SleuthSpanCreatorAspectFluxTests { return new TestBean(tracer); } - @Bean Reporter spanReporter() { + @Bean + Reporter spanReporter() { return new ArrayListSpanReporter(); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectMonoTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectMonoTests.java index a4f172714..2a80864f6 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectMonoTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectMonoTests.java @@ -46,17 +46,24 @@ import static reactor.core.publisher.Mono.just; @SpringBootTest(classes = SleuthSpanCreatorAspectMonoTests.TestConfiguration.class) @RunWith(SpringJUnit4ClassRunner.class) public class SleuthSpanCreatorAspectMonoTests { - - @Autowired TestBeanInterface testBean; - @Autowired TestBeanOuter testBeanOuter; - @Autowired Tracer tracer; - @Autowired ArrayListSpanReporter reporter; - + + @Autowired + TestBeanInterface testBean; + + @Autowired + TestBeanOuter testBeanOuter; + + @Autowired + Tracer tracer; + + @Autowired + ArrayListSpanReporter reporter; + @Before public void setup() { this.reporter.clear(); } - + @Test public void shouldCreateSpanWhenAnnotationOnInterfaceMethod() { Mono mono = this.testBean.testMethod(); @@ -71,7 +78,7 @@ public class SleuthSpanCreatorAspectMonoTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWhenAnnotationOnClassMethod() { Mono mono = this.testBean.testMethod2(); @@ -86,7 +93,7 @@ public class SleuthSpanCreatorAspectMonoTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWithCustomNameWhenAnnotationOnClassMethod() { Mono mono = this.testBean.testMethod3(); @@ -102,7 +109,7 @@ public class SleuthSpanCreatorAspectMonoTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWithCustomNameWhenAnnotationOnInterfaceMethod() { Mono mono = this.testBean.testMethod4(); @@ -117,7 +124,7 @@ public class SleuthSpanCreatorAspectMonoTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWithTagWhenAnnotationOnInterfaceMethod() { // tag::execution[] @@ -135,7 +142,7 @@ public class SleuthSpanCreatorAspectMonoTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWithTagWhenAnnotationOnClassMethod() { Mono mono = this.testBean.testMethod6("test"); @@ -178,8 +185,7 @@ public class SleuthSpanCreatorAspectMonoTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("custom-name-on-test-method9"); - then(spans.get(0).tags()) - .containsEntry("class", "TestBean") + then(spans.get(0).tags()).containsEntry("class", "TestBean") .containsEntry("method", "testMethod9"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); @@ -195,18 +201,18 @@ public class SleuthSpanCreatorAspectMonoTests { then(this.reporter.getSpans()).isEmpty(); mono.block(); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("customTestTag10", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).tags()).containsEntry("customTestTag10", "test"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -218,11 +224,10 @@ public class SleuthSpanCreatorAspectMonoTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("test-method10"); - then(spans.get(0).tags()) - .containsEntry("customTestTag10", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).tags()).containsEntry("customTestTag10", "test"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -237,18 +242,18 @@ public class SleuthSpanCreatorAspectMonoTests { then(this.reporter.getSpans()).isEmpty(); mono.block(); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("customTestTag10", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).tags()).containsEntry("customTestTag10", "test"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -264,20 +269,20 @@ public class SleuthSpanCreatorAspectMonoTests { then(this.reporter.getSpans()).isEmpty(); mono.block(); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("class", "TestBean") + then(spans.get(0).tags()).containsEntry("class", "TestBean") .containsEntry("method", "testMethod11") .containsEntry("customTestTag11", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -290,14 +295,14 @@ public class SleuthSpanCreatorAspectMonoTests { then(this.reporter.getSpans()).isEmpty(); mono.block(); - } catch (RuntimeException ignored) { + } + catch (RuntimeException ignored) { } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("test-method12"); - then(spans.get(0).tags()) - .containsEntry("testTag12", "test") + then(spans.get(0).tags()).containsEntry("testTag12", "test") .containsEntry("error", "test exception 12"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); @@ -315,20 +320,20 @@ public class SleuthSpanCreatorAspectMonoTests { mono.block(); // end::continue_span_execution[] - } catch (RuntimeException ignored) { - } finally { + } + catch (RuntimeException ignored) { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("error", "test exception 13"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("testMethod13.before", "testMethod13.afterFailure", - "testMethod13.after"); + then(spans.get(0).tags()).containsEntry("error", "test exception 13"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("testMethod13.before", + "testMethod13.afterFailure", "testMethod13.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -360,7 +365,8 @@ public class SleuthSpanCreatorAspectMonoTests { @Test public void shouldReturnNewSpanFromTraceContextOuter() { - Mono, Long>> mono = this.testBeanOuter.outerNewSpanInTraceContext(); + Mono, Long>> mono = this.testBeanOuter + .outerNewSpanInTraceContext(); then(this.reporter.getSpans()).isEmpty(); @@ -397,7 +403,8 @@ public class SleuthSpanCreatorAspectMonoTests { @Test public void shouldReturnNewSpanFromSubscriberContextOuter() { - Mono, Long>> mono = this.testBeanOuter.outerNewSpanInSubscriberContext(); + Mono, Long>> mono = this.testBeanOuter + .outerNewSpanInSubscriberContext(); then(this.reporter.getSpans()).isEmpty(); @@ -417,7 +424,7 @@ public class SleuthSpanCreatorAspectMonoTests { then(this.tracer.currentSpan()).isNull(); } - private static String toHexString(long value){ + private static String toHexString(long value) { return StringUtils.leftPad(Long.toHexString(value), 16, '0'); } @@ -475,11 +482,13 @@ public class SleuthSpanCreatorAspectMonoTests { @NewSpan(name = "spanInSubscriberContext") Mono newSpanInSubscriberContext(); + } - + protected static class TestBean implements TestBeanInterface { public static final String TEST_STRING = "Test String"; + public static final Mono TEST_MONO = Mono.defer(() -> just(TEST_STRING)); private final Tracer tracer; @@ -511,7 +520,7 @@ public class SleuthSpanCreatorAspectMonoTests { public Mono testMethod4() { return TEST_MONO; } - + @Override public Mono testMethod5(String test) { return TEST_MONO; @@ -540,12 +549,14 @@ public class SleuthSpanCreatorAspectMonoTests { } @Override - public Mono testMethod10(@SpanTag(value = "customTestTag10") String param) { + public Mono testMethod10( + @SpanTag(value = "customTestTag10") String param) { return TEST_MONO; } @Override - public Mono testMethod10_v2(@SpanTag(key = "customTestTag10") String param) { + public Mono testMethod10_v2( + @SpanTag(key = "customTestTag10") String param) { return TEST_MONO; } @@ -557,12 +568,14 @@ public class SleuthSpanCreatorAspectMonoTests { @Override public Mono testMethod12(String param) { - return Mono.defer(() -> Mono.error(new RuntimeException("test exception 12"))); + return Mono + .defer(() -> Mono.error(new RuntimeException("test exception 12"))); } @Override public Mono testMethod13() { - return Mono.defer(() -> Mono.error(new RuntimeException("test exception 13"))); + return Mono + .defer(() -> Mono.error(new RuntimeException("test exception 13"))); } @Override @@ -572,14 +585,16 @@ public class SleuthSpanCreatorAspectMonoTests { @Override public Mono newSpanInSubscriberContext() { - return Mono.subscriberContext() - .flatMap(context -> Mono.just(tracer.currentSpan().context().spanId())); + return Mono.subscriberContext().flatMap( + context -> Mono.just(tracer.currentSpan().context().spanId())); } + } protected static class TestBeanOuter { private final Tracer tracer; + private final TestBeanInterface testBeanInterface; public TestBeanOuter(Tracer tracer, TestBeanInterface testBeanInterface) { @@ -589,20 +604,30 @@ public class SleuthSpanCreatorAspectMonoTests { @NewSpan(name = "outerSpanInTraceContext") public Mono, Long>> outerNewSpanInTraceContext() { - return Mono.defer(() -> Mono.just(tracer.currentSpan().context().spanId()) - .zipWith(testBeanInterface.newSpanInTraceContext()) - .map(pair -> Pair.of(Pair.of(pair.getT1(), tracer.currentSpan().context().spanId()), pair.getT2()))); + return Mono + .defer(() -> Mono.just(tracer.currentSpan().context().spanId()) + .zipWith( + testBeanInterface.newSpanInTraceContext()) + .map(pair -> Pair.of( + Pair.of(pair.getT1(), + tracer.currentSpan().context().spanId()), + pair.getT2()))); } @NewSpan(name = "outerSpanInSubscriberContext") public Mono, Long>> outerNewSpanInSubscriberContext() { return Mono.subscriberContext() .flatMap(context -> Mono.just(tracer.currentSpan().context().spanId()) - .zipWith(testBeanInterface.newSpanInSubscriberContext()) - .map(pair -> Pair.of(Pair.of(pair.getT1(), tracer.currentSpan().context().spanId()), pair.getT2()))); + .zipWith( + testBeanInterface.newSpanInSubscriberContext()) + .map(pair -> Pair.of( + Pair.of(pair.getT1(), + tracer.currentSpan().context().spanId()), + pair.getT2()))); } + } - + @Configuration @EnableAutoConfiguration protected static class TestConfiguration { @@ -617,12 +642,16 @@ public class SleuthSpanCreatorAspectMonoTests { return new TestBeanOuter(tracer, testBean); } - @Bean Reporter spanReporter() { + @Bean + Reporter spanReporter() { return new ArrayListSpanReporter(); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectNegativeTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectNegativeTests.java index 8d66919c9..27af6fccd 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectNegativeTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectNegativeTests.java @@ -38,9 +38,14 @@ import static org.assertj.core.api.BDDAssertions.then; @SpringBootTest(classes = SleuthSpanCreatorAspectNegativeTests.TestConfiguration.class) public class SleuthSpanCreatorAspectNegativeTests { - @Autowired NotAnnotatedTestBeanInterface testBean; - @Autowired TestBeanInterface annotatedTestBean; - @Autowired ArrayListSpanReporter reporter; + @Autowired + NotAnnotatedTestBeanInterface testBean; + + @Autowired + TestBeanInterface annotatedTestBean; + + @Autowired + ArrayListSpanReporter reporter; @Before public void setup() { @@ -62,10 +67,11 @@ public class SleuthSpanCreatorAspectNegativeTests { then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("test-method"); } - + protected interface NotAnnotatedTestBeanInterface { void testMethod(); + } protected static class NotAnnotatedTestBean implements NotAnnotatedTestBeanInterface { @@ -75,27 +81,28 @@ public class SleuthSpanCreatorAspectNegativeTests { } } - + protected interface TestBeanInterface { - + @NewSpan void testMethod(); - + void testMethod2(); - + void testMethod3(); - + @NewSpan(name = "testMethod4") void testMethod4(); - + @NewSpan(name = "testMethod5") void testMethod5(@SpanTag("testTag") String test); - + void testMethod6(String test); - + void testMethod7(); + } - + protected static class TestBean implements TestBeanInterface { @Override @@ -115,7 +122,7 @@ public class SleuthSpanCreatorAspectNegativeTests { @Override public void testMethod4() { } - + @Override public void testMethod5(String test) { } @@ -123,18 +130,21 @@ public class SleuthSpanCreatorAspectNegativeTests { @NewSpan(name = "testMethod6") @Override public void testMethod6(@SpanTag("testTag6") String test) { - + } @Override public void testMethod7() { } + } @Configuration @EnableAutoConfiguration protected static class TestConfiguration { - @Bean Reporter spanReporter() { + + @Bean + Reporter spanReporter() { return new ArrayListSpanReporter(); } @@ -152,5 +162,7 @@ public class SleuthSpanCreatorAspectNegativeTests { public Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectTests.java index 366199891..eca0686c8 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectTests.java @@ -40,16 +40,21 @@ import static org.assertj.core.api.BDDAssertions.then; @SpringBootTest(classes = SleuthSpanCreatorAspectTests.TestConfiguration.class) @RunWith(SpringJUnit4ClassRunner.class) public class SleuthSpanCreatorAspectTests { - - @Autowired TestBeanInterface testBean; - @Autowired Tracer tracer; - @Autowired ArrayListSpanReporter reporter; - + + @Autowired + TestBeanInterface testBean; + + @Autowired + Tracer tracer; + + @Autowired + ArrayListSpanReporter reporter; + @Before public void setup() { this.reporter.clear(); } - + @Test public void shouldCreateSpanWhenAnnotationOnInterfaceMethod() { this.testBean.testMethod(); @@ -60,7 +65,7 @@ public class SleuthSpanCreatorAspectTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWhenAnnotationOnClassMethod() { this.testBean.testMethod2(); @@ -71,7 +76,7 @@ public class SleuthSpanCreatorAspectTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWithCustomNameWhenAnnotationOnClassMethod() { this.testBean.testMethod3(); @@ -82,7 +87,7 @@ public class SleuthSpanCreatorAspectTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWithCustomNameWhenAnnotationOnInterfaceMethod() { this.testBean.testMethod4(); @@ -93,7 +98,7 @@ public class SleuthSpanCreatorAspectTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWithTagWhenAnnotationOnInterfaceMethod() { // tag::execution[] @@ -107,7 +112,7 @@ public class SleuthSpanCreatorAspectTests { then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } - + @Test public void shouldCreateSpanWithTagWhenAnnotationOnClassMethod() { this.testBean.testMethod6("test"); @@ -138,8 +143,7 @@ public class SleuthSpanCreatorAspectTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("custom-name-on-test-method9"); - then(spans.get(0).tags()) - .containsEntry("class", "TestBean") + then(spans.get(0).tags()).containsEntry("class", "TestBean") .containsEntry("method", "testMethod9"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); @@ -151,18 +155,18 @@ public class SleuthSpanCreatorAspectTests { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { this.testBean.testMethod10("test"); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("customTestTag10", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).tags()).containsEntry("customTestTag10", "test"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -174,11 +178,10 @@ public class SleuthSpanCreatorAspectTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("test-method10"); - then(spans.get(0).tags()) - .containsEntry("customTestTag10", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).tags()).containsEntry("customTestTag10", "test"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -189,18 +192,18 @@ public class SleuthSpanCreatorAspectTests { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { this.testBean.testMethod10_v2("test"); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("customTestTag10", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).tags()).containsEntry("customTestTag10", "test"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -213,20 +216,20 @@ public class SleuthSpanCreatorAspectTests { // tag::continue_span_execution[] this.testBean.testMethod11("test"); // end::continue_span_execution[] - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("class", "TestBean") + then(spans.get(0).tags()).containsEntry("class", "TestBean") .containsEntry("method", "testMethod11") .containsEntry("customTestTag11", "test"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("customTest.before", "customTest.after"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("customTest.before", + "customTest.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -235,14 +238,14 @@ public class SleuthSpanCreatorAspectTests { public void shouldAddErrorTagWhenExceptionOccurredInNewSpan() { try { this.testBean.testMethod12("test"); - } catch (RuntimeException ignored) { + } + catch (RuntimeException ignored) { } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("test-method12"); - then(spans.get(0).tags()) - .containsEntry("testTag12", "test") + then(spans.get(0).tags()).containsEntry("testTag12", "test") .containsEntry("error", "test exception 12"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); @@ -256,20 +259,20 @@ public class SleuthSpanCreatorAspectTests { // tag::continue_span_execution[] this.testBean.testMethod13(); // end::continue_span_execution[] - } catch (RuntimeException ignored) { - } finally { + } + catch (RuntimeException ignored) { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).name()).isEqualTo("foo"); - then(spans.get(0).tags()) - .containsEntry("error", "test exception 13"); - then(spans.get(0).annotations() - .stream().map(Annotation::value).collect(Collectors.toList())) - .contains("testMethod13.before", "testMethod13.afterFailure", - "testMethod13.after"); + then(spans.get(0).tags()).containsEntry("error", "test exception 13"); + then(spans.get(0).annotations().stream().map(Annotation::value) + .collect(Collectors.toList())).contains("testMethod13.before", + "testMethod13.afterFailure", "testMethod13.after"); then(spans.get(0).duration()).isNotZero(); then(this.tracer.currentSpan()).isNull(); } @@ -282,14 +285,14 @@ public class SleuthSpanCreatorAspectTests { then(spans).isEmpty(); then(this.tracer.currentSpan()).isNull(); } - + protected interface TestBeanInterface { // tag::annotated_method[] @NewSpan void testMethod(); // end::annotated_method[] - + void testMethod2(); @NewSpan(name = "interfaceCustomNameOnTestMethod3") @@ -306,7 +309,7 @@ public class SleuthSpanCreatorAspectTests { // end::custom_name_and_tag_on_annotated_method[] void testMethod6(String test); - + void testMethod7(); @NewSpan(name = "customNameOnTestMethod8") @@ -331,8 +334,9 @@ public class SleuthSpanCreatorAspectTests { @ContinueSpan(log = "testMethod13") void testMethod13(); + } - + protected static class TestBean implements TestBeanInterface { @Override @@ -354,7 +358,7 @@ public class SleuthSpanCreatorAspectTests { @Override public void testMethod4() { } - + @Override public void testMethod5(String test) { } @@ -362,7 +366,7 @@ public class SleuthSpanCreatorAspectTests { @NewSpan(name = "customNameOnTestMethod6") @Override public void testMethod6(@SpanTag("testTag6") String test) { - + } @Override @@ -405,8 +409,9 @@ public class SleuthSpanCreatorAspectTests { public void testMethod13() { throw new RuntimeException("test exception 13"); } + } - + @Configuration @EnableAutoConfiguration protected static class TestConfiguration { @@ -416,12 +421,16 @@ public class SleuthSpanCreatorAspectTests { return new TestBean(); } - @Bean Reporter spanReporter() { + @Bean + Reporter spanReporter() { return new ArrayListSpanReporter(); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectWebFluxTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectWebFluxTests.java index 00f4a66b6..70e8979d0 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectWebFluxTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorAspectWebFluxTests.java @@ -47,16 +47,16 @@ import zipkin2.reporter.Reporter; import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest( - properties = {"spring.main.web-application-type=reactive"}, - classes = { +@SpringBootTest(properties = { "spring.main.web-application-type=reactive" }, classes = { SleuthSpanCreatorAspectWebFluxTests.TestEndpoint.class, - SleuthSpanCreatorAspectWebFluxTests.TestConfiguration.class} - , webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) + SleuthSpanCreatorAspectWebFluxTests.TestConfiguration.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class SleuthSpanCreatorAspectWebFluxTests { - @Autowired Tracer tracer; - @Autowired ArrayListSpanReporter reporter; + @Autowired + Tracer tracer; + + @Autowired + ArrayListSpanReporter reporter; @Before public void setup() { @@ -69,11 +69,11 @@ public class SleuthSpanCreatorAspectWebFluxTests { private final WebClient webClient = WebClient.create(); private static final ConcurrentLinkedQueue spanIdsInHttpTrace = new ConcurrentLinkedQueue<>(); - + @Test public void shouldReturnSpanFromWebFluxTraceContext() { - Mono mono = webClient.get().uri("http://localhost:"+port+"/test/ping") + Mono mono = webClient.get().uri("http://localhost:" + port + "/test/ping") .retrieve().bodyToMono(Long.class); then(this.reporter.getSpans()).isEmpty(); @@ -91,8 +91,9 @@ public class SleuthSpanCreatorAspectWebFluxTests { @Test public void shouldReturnSpanFromWebFluxSubscriptionContext() { - Mono mono = webClient.get().uri("http://localhost:"+port+"/test/pingFromContext") - .retrieve().bodyToMono(Long.class); + Mono mono = webClient.get() + .uri("http://localhost:" + port + "/test/pingFromContext").retrieve() + .bodyToMono(Long.class); then(this.reporter.getSpans()).isEmpty(); @@ -109,8 +110,9 @@ public class SleuthSpanCreatorAspectWebFluxTests { @Test public void shouldContinueSpanInWebFlux() { - Mono mono = webClient.get().uri("http://localhost:"+port+"/test/continueSpan") - .retrieve().bodyToMono(Long.class); + Mono mono = webClient.get() + .uri("http://localhost:" + port + "/test/continueSpan").retrieve() + .bodyToMono(Long.class); then(this.reporter.getSpans()).isEmpty(); @@ -127,8 +129,9 @@ public class SleuthSpanCreatorAspectWebFluxTests { @Test public void shouldCreateNewSpanInWebFlux() { - Mono mono = webClient.get().uri("http://localhost:"+port+"/test/newSpan1") - .retrieve().bodyToMono(Long.class); + Mono mono = webClient.get() + .uri("http://localhost:" + port + "/test/newSpan1").retrieve() + .bodyToMono(Long.class); then(this.reporter.getSpans()).isEmpty(); @@ -146,8 +149,9 @@ public class SleuthSpanCreatorAspectWebFluxTests { @Test public void shouldCreateNewSpanInWebFluxInSubscriberContext() { - Mono mono = webClient.get().uri("http://localhost:"+port+"/test/newSpan2") - .retrieve().bodyToMono(Long.class); + Mono mono = webClient.get() + .uri("http://localhost:" + port + "/test/newSpan2").retrieve() + .bodyToMono(Long.class); then(this.reporter.getSpans()).isEmpty(); @@ -167,7 +171,7 @@ public class SleuthSpanCreatorAspectWebFluxTests { spanIdsInHttpTrace.clear(); - Mono mono = webClient.get().uri("http://localhost:"+port+"/test/ping") + Mono mono = webClient.get().uri("http://localhost:" + port + "/test/ping") .retrieve().bodyToMono(Long.class); then(this.reporter.getSpans()).isEmpty(); @@ -178,18 +182,15 @@ public class SleuthSpanCreatorAspectWebFluxTests { then(spans).hasSize(1); then(spans.get(0).kind()).isEqualTo(Span.Kind.SERVER); then(spans.get(0).name()).isEqualTo("get /test/ping"); - then(spans.get(0).id()) - .isEqualTo(toHexString(newSpanId)) + then(spans.get(0).id()).isEqualTo(toHexString(newSpanId)) .isEqualTo(toHexString(spanIdsInHttpTrace.poll())); then(this.tracer.currentSpan()).isNull(); } - - private static String toHexString(long value){ + private static String toHexString(long value) { return StringUtils.leftPad(Long.toHexString(value), 16, '0'); } - @Configuration @EnableAutoConfiguration @DisableWebFluxSecurity @@ -200,22 +201,27 @@ public class SleuthSpanCreatorAspectWebFluxTests { return new TestBean(tracer); } - @Bean Reporter spanReporter() { + @Bean + Reporter spanReporter() { return new ArrayListSpanReporter(); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean AccessLoggingHttpTraceRepository accessLoggingHttpTraceRepository(){ + @Bean + AccessLoggingHttpTraceRepository accessLoggingHttpTraceRepository() { return new AccessLoggingHttpTraceRepository(); } + } static class AccessLoggingHttpTraceRepository implements HttpTraceRepository { - @Autowired Tracer tracer; + @Autowired + Tracer tracer; @Override public List findAll() { @@ -226,14 +232,18 @@ public class SleuthSpanCreatorAspectWebFluxTests { public void add(HttpTrace trace) { spanIdsInHttpTrace.add(tracer.currentSpan().context().spanId()); } + } @RestController @RequestMapping("/test") static class TestEndpoint { - @Autowired Tracer tracer; - @Autowired TestBean testBean; + @Autowired + Tracer tracer; + + @Autowired + TestBean testBean; @GetMapping("/ping") public Mono ping() { @@ -242,8 +252,8 @@ public class SleuthSpanCreatorAspectWebFluxTests { @GetMapping("/pingFromContext") public Mono pingFromContext() { - return Mono.subscriberContext() - .flatMap(context -> Mono.just(tracer.currentSpan().context().spanId())); + return Mono.subscriberContext().flatMap( + context -> Mono.just(tracer.currentSpan().context().spanId())); } @GetMapping("/continueSpan") @@ -260,6 +270,7 @@ public class SleuthSpanCreatorAspectWebFluxTests { public Mono newSpan2() { return testBean.newSpanInSubscriberContext(); } + } static class TestBean { @@ -282,8 +293,10 @@ public class SleuthSpanCreatorAspectWebFluxTests { @NewSpan(name = "newSpanInSubscriberContext") public Mono newSpanInSubscriberContext() { - return Mono.subscriberContext() - .flatMap(context -> Mono.defer(() -> Mono.just(tracer.currentSpan().context().spanId()))); + return Mono.subscriberContext().flatMap(context -> Mono + .defer(() -> Mono.just(tracer.currentSpan().context().spanId()))); } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorCircularDependencyTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorCircularDependencyTests.java index a0c0cbfd8..b1c8cf4a2 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorCircularDependencyTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SleuthSpanCreatorCircularDependencyTests.java @@ -30,36 +30,52 @@ import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest(classes = SleuthSpanCreatorCircularDependencyTests.TestConfiguration.class) @RunWith(SpringRunner.class) public class SleuthSpanCreatorCircularDependencyTests { - @Test public void contextLoads() throws Exception { + + @Test + public void contextLoads() throws Exception { } private static class Service1 { - @Autowired private Service2 service2; - @NewSpan public void foo() { + @Autowired + private Service2 service2; + + @NewSpan + public void foo() { } + } private static class Service2 { - @Autowired private Service1 service1; - @NewSpan public void bar() { + @Autowired + private Service1 service1; + + @NewSpan + public void bar() { } + } @Configuration @EnableAutoConfiguration protected static class TestConfiguration { - @Bean Reporter spanReporter() { + + @Bean + Reporter spanReporter() { return new ArrayListSpanReporter(); } - @Bean public Service1 service1() { + @Bean + public Service1 service1() { return new Service1(); } - @Bean public Service2 service2() { + @Bean + public Service2 service2() { return new Service2(); } + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SpanTagAnnotationHandlerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SpanTagAnnotationHandlerTests.java index 6bde25dc2..68f01ecfb 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SpanTagAnnotationHandlerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SpanTagAnnotationHandlerTests.java @@ -38,8 +38,12 @@ import static org.assertj.core.api.Assertions.fail; @RunWith(SpringJUnit4ClassRunner.class) public class SpanTagAnnotationHandlerTests { - @Autowired BeanFactory beanFactory; - @Autowired TagValueResolver tagValueResolver; + @Autowired + BeanFactory beanFactory; + + @Autowired + TagValueResolver tagValueResolver; + SpanTagAnnotationHandler handler; @Before @@ -48,38 +52,47 @@ public class SpanTagAnnotationHandlerTests { } @Test - public void shouldUseCustomTagValueResolver() throws NoSuchMethodException, SecurityException { - Method method = AnnotationMockClass.class.getMethod("getAnnotationForTagValueResolver", String.class); + public void shouldUseCustomTagValueResolver() + throws NoSuchMethodException, SecurityException { + Method method = AnnotationMockClass.class + .getMethod("getAnnotationForTagValueResolver", String.class); Annotation annotation = method.getParameterAnnotations()[0][0]; if (annotation instanceof SpanTag) { String resolvedValue = handler.resolveTagValue((SpanTag) annotation, "test"); assertThat(resolvedValue).isEqualTo("Value from myCustomTagValueResolver"); - } else { - fail("Annotation was not SleuthSpanTag"); } - } - - @Test - public void shouldUseTagValueExpression() throws NoSuchMethodException, SecurityException { - Method method = AnnotationMockClass.class.getMethod("getAnnotationForTagValueExpression", String.class); - Annotation annotation = method.getParameterAnnotations()[0][0]; - if (annotation instanceof SpanTag) { - String resolvedValue = handler.resolveTagValue((SpanTag) annotation, "test"); - - assertThat(resolvedValue).isEqualTo("hello characters"); - } else { + else { fail("Annotation was not SleuthSpanTag"); } } @Test - public void shouldReturnArgumentToString() throws NoSuchMethodException, SecurityException { - Method method = AnnotationMockClass.class.getMethod("getAnnotationForArgumentToString", Long.class); + public void shouldUseTagValueExpression() + throws NoSuchMethodException, SecurityException { + Method method = AnnotationMockClass.class + .getMethod("getAnnotationForTagValueExpression", String.class); + Annotation annotation = method.getParameterAnnotations()[0][0]; + if (annotation instanceof SpanTag) { + String resolvedValue = handler.resolveTagValue((SpanTag) annotation, "test"); + + assertThat(resolvedValue).isEqualTo("hello characters"); + } + else { + fail("Annotation was not SleuthSpanTag"); + } + } + + @Test + public void shouldReturnArgumentToString() + throws NoSuchMethodException, SecurityException { + Method method = AnnotationMockClass.class + .getMethod("getAnnotationForArgumentToString", Long.class); Annotation annotation = method.getParameterAnnotations()[0][0]; if (annotation instanceof SpanTag) { String resolvedValue = handler.resolveTagValue((SpanTag) annotation, 15); assertThat(resolvedValue).isEqualTo("15"); - } else { + } + else { fail("Annotation was not SleuthSpanTag"); } } @@ -88,13 +101,15 @@ public class SpanTagAnnotationHandlerTests { // tag::resolver_bean[] @NewSpan - public void getAnnotationForTagValueResolver(@SpanTag(key = "test", resolver = TagValueResolver.class) String test) { + public void getAnnotationForTagValueResolver( + @SpanTag(key = "test", resolver = TagValueResolver.class) String test) { } // end::resolver_bean[] // tag::spel[] @NewSpan - public void getAnnotationForTagValueExpression(@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) { + public void getAnnotationForTagValueExpression( + @SpanTag(key = "test", expression = "'hello' + ' characters'") String test) { } // end::spel[] @@ -103,8 +118,9 @@ public class SpanTagAnnotationHandlerTests { public void getAnnotationForArgumentToString(@SpanTag("test") Long param) { } // end::toString[] + } - + @Configuration @EnableAutoConfiguration protected static class TestConfiguration { @@ -116,9 +132,11 @@ public class SpanTagAnnotationHandlerTests { } // end::custom_resolver[] - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } + } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SpelTagValueExpressionResolverTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SpelTagValueExpressionResolverTests.java index 13ff87336..3f36324b9 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SpelTagValueExpressionResolverTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/annotation/SpelTagValueExpressionResolverTests.java @@ -24,6 +24,7 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ public class SpelTagValueExpressionResolverTests { + @Test public void should_use_spel_to_resolve_a_value() throws Exception { SpelTagValueExpressionResolver resolver = new SpelTagValueExpressionResolver(); @@ -36,21 +37,28 @@ public class SpelTagValueExpressionResolverTests { } public static class MyObject { + public String name; + } @Test - public void should_use_to_string_if_expression_is_not_analyzed_properly() throws Exception { + public void should_use_to_string_if_expression_is_not_analyzed_properly() + throws Exception { SpelTagValueExpressionResolver resolver = new SpelTagValueExpressionResolver(); String resolved = resolver.resolve("invalid() structure + 1", new Foo()); then(resolved).isEqualTo("BAR"); } + } class Foo { - @Override public String toString() { + + @Override + public String toString() { return "BAR"; } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationWithDisabledSleuthTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationWithDisabledSleuthTests.java index bc41851da..e3c6db5b5 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationWithDisabledSleuthTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationWithDisabledSleuthTests.java @@ -35,17 +35,18 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = TraceAutoConfigurationWithDisabledSleuthTests.Config.class, - properties = "spring.sleuth.enabled=false", - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(classes = TraceAutoConfigurationWithDisabledSleuthTests.Config.class, properties = "spring.sleuth.enabled=false", webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles("disabled") public class TraceAutoConfigurationWithDisabledSleuthTests { - private static final Log log = LogFactory.getLog( - TraceAutoConfigurationWithDisabledSleuthTests.class); + private static final Log log = LogFactory + .getLog(TraceAutoConfigurationWithDisabledSleuthTests.class); - @Rule public OutputCapture capture = new OutputCapture(); - @Autowired(required = false) Tracing tracing; + @Rule + public OutputCapture capture = new OutputCapture(); + + @Autowired(required = false) + Tracing tracing; @Test public void shouldStartContext() { @@ -62,22 +63,28 @@ public class TraceAutoConfigurationWithDisabledSleuthTests { @EnableAutoConfiguration @Configuration static class Config { + @Bean public FactoryBean secureRandom() { return new FactoryBean() { - @Override public SecureRandom getObject() throws Exception { + @Override + public SecureRandom getObject() throws Exception { return new SecureRandom(); } - @Override public Class getObjectType() { + @Override + public Class getObjectType() { return SecureRandom.class; } - @Override public boolean isSingleton() { + @Override + public boolean isSingleton() { return true; } }; } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/documentation/SpringCloudSleuthDocTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/documentation/SpringCloudSleuthDocTests.java index 1e694a67f..53ab3f3a7 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/documentation/SpringCloudSleuthDocTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/documentation/SpringCloudSleuthDocTests.java @@ -53,13 +53,12 @@ import static org.assertj.core.api.BDDAssertions.then; public class SpringCloudSleuthDocTests { ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .sampler(Sampler.ALWAYS_SAMPLE) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .sampler(Sampler.ALWAYS_SAMPLE).spanReporter(this.reporter).build(); + Tracer tracer = tracing.tracer(); @Before @@ -69,21 +68,25 @@ public class SpringCloudSleuthDocTests { @Configuration public class SamplingConfiguration { + // tag::always_sampler[] @Bean public Sampler defaultSampler() { return Sampler.ALWAYS_SAMPLE; } // end::always_sampler[] + } // tag::span_name_annotation[] @SpanName("calculateTax") class TaxCountingRunnable implements Runnable { - @Override public void run() { + @Override + public void run() { // perform logic } + } // end::span_name_annotation[] @@ -103,8 +106,7 @@ public class SpringCloudSleuthDocTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); - then(spans.get(0).name()) - .isEqualTo("calculatetax"); + then(spans.get(0).name()).isEqualTo("calculatetax"); } @Test @@ -115,11 +117,13 @@ public class SpringCloudSleuthDocTests { // tag::span_name_to_string_runnable_execution[] Runnable runnable = new TraceRunnable(tracing, spanNamer, new Runnable() { - @Override public void run() { + @Override + public void run() { // perform logic } - @Override public String toString() { + @Override + public String toString() { return "calculateTax"; } }); @@ -130,8 +134,7 @@ public class SpringCloudSleuthDocTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); - then(spans.get(0).name()) - .isEqualTo("calculatetax"); + then(spans.get(0).name()).isEqualTo("calculatetax"); executorService.shutdown(); } @@ -150,7 +153,8 @@ public class SpringCloudSleuthDocTests { // ... // You can log an event on a span newSpan.annotate("taxCalculated"); - } finally { + } + finally { // Once done remember to finish the span. This will allow collecting // the span to send it to Zipkin newSpan.finish(); @@ -159,10 +163,8 @@ public class SpringCloudSleuthDocTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); - then(spans.get(0).name()) - .isEqualTo("calculatetax"); - then(spans.get(0).tags()) - .containsEntry("taxValue", "10"); + then(spans.get(0).name()).isEqualTo("calculatetax"); + then(spans.get(0).tags()).containsEntry("taxValue", "10"); then(spans.get(0).annotations()).hasSize(1); } @@ -173,35 +175,34 @@ public class SpringCloudSleuthDocTests { Span newSpan = this.tracer.nextSpan().name("calculateTax"); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(newSpan.start())) { executorService.submit(() -> { - // tag::manual_span_continuation[] - // let's assume that we're in a thread Y and we've received - // the `initialSpan` from thread X - Span continuedSpan = this.tracer.toSpan(newSpan.context()); - try { - // ... - // You can tag a span - continuedSpan.tag("taxValue", taxValue); - // ... - // You can log an event on a span - continuedSpan.annotate("taxCalculated"); - } finally { - // Once done remember to flush the span. That means that - // it will get reported but the span itself is not yet finished - continuedSpan.flush(); - } - // end::manual_span_continuation[] - } - ).get(); - } finally { + // tag::manual_span_continuation[] + // let's assume that we're in a thread Y and we've received + // the `initialSpan` from thread X + Span continuedSpan = this.tracer.toSpan(newSpan.context()); + try { + // ... + // You can tag a span + continuedSpan.tag("taxValue", taxValue); + // ... + // You can log an event on a span + continuedSpan.annotate("taxCalculated"); + } + finally { + // Once done remember to flush the span. That means that + // it will get reported but the span itself is not yet finished + continuedSpan.flush(); + } + // end::manual_span_continuation[] + }).get(); + } + finally { newSpan.finish(); } List spans = this.reporter.getSpans(); BDDAssertions.then(spans).hasSize(1); - BDDAssertions.then(spans.get(0).name()) - .isEqualTo("calculatetax"); - BDDAssertions.then(spans.get(0).tags()) - .containsEntry("taxValue", "10"); + BDDAssertions.then(spans.get(0).name()).isEqualTo("calculatetax"); + BDDAssertions.then(spans.get(0).tags()).containsEntry("taxValue", "10"); BDDAssertions.then(spans.get(0).annotations()).hasSize(1); executorService.shutdown(); } @@ -213,37 +214,37 @@ public class SpringCloudSleuthDocTests { Span initialSpan = this.tracer.nextSpan().name("calculateTax").start(); executorService.submit(() -> { - // tag::manual_span_joining[] - // let's assume that we're in a thread Y and we've received - // the `initialSpan` from thread X. `initialSpan` will be the parent - // of the `newSpan` - Span newSpan = null; - try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initialSpan)) { - newSpan = this.tracer.nextSpan().name("calculateCommission"); - // ... - // You can tag a span - newSpan.tag("commissionValue", commissionValue); - // ... - // You can log an event on a span - newSpan.annotate("commissionCalculated"); - } finally { - // Once done remember to finish the span. This will allow collecting - // the span to send it to Zipkin. The tags and events set on the - // newSpan will not be present on the parent - if (newSpan != null) { - newSpan.finish(); - } - } - // end::manual_span_joining[] + // tag::manual_span_joining[] + // let's assume that we're in a thread Y and we've received + // the `initialSpan` from thread X. `initialSpan` will be the parent + // of the `newSpan` + Span newSpan = null; + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initialSpan)) { + newSpan = this.tracer.nextSpan().name("calculateCommission"); + // ... + // You can tag a span + newSpan.tag("commissionValue", commissionValue); + // ... + // You can log an event on a span + newSpan.annotate("commissionCalculated"); + } + finally { + // Once done remember to finish the span. This will allow collecting + // the span to send it to Zipkin. The tags and events set on the + // newSpan will not be present on the parent + if (newSpan != null) { + newSpan.finish(); } - ).get(); + } + // end::manual_span_joining[] + }).get(); List spans = this.reporter.getSpans(); Optional calculateTax = spans.stream() .filter(span -> span.name().equals("calculatecommission")).findFirst(); BDDAssertions.then(calculateTax).isPresent(); - BDDAssertions.then(calculateTax.get().tags()) - .containsEntry("commissionValue", "10"); + BDDAssertions.then(calculateTax.get().tags()).containsEntry("commissionValue", + "10"); BDDAssertions.then(calculateTax.get().annotations()).hasSize(1); executorService.shutdown(); } @@ -294,11 +295,13 @@ public class SpringCloudSleuthDocTests { "calculateTax"); // Wrapping `Callable` with `Tracing`. That way the current span will be available // in the thread of `Callable` - Callable traceCallableFromTracer = tracing.currentTraceContext().wrap(callable); + Callable traceCallableFromTracer = tracing.currentTraceContext() + .wrap(callable); // end::trace_callable[] } private String someLogic() { return "some logic"; } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/DefaultTestAutoConfiguration.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/DefaultTestAutoConfiguration.java index d113a0938..652dfc9ec 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/DefaultTestAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/DefaultTestAutoConfiguration.java @@ -29,9 +29,10 @@ import org.springframework.context.annotation.Configuration; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @EnableAutoConfiguration(exclude = { LoadBalancerAutoConfiguration.class, - JmxAutoConfiguration.class}) -// ,TraceSpringIntegrationAutoConfiguration.class, -// TraceWebSocketAutoConfiguration.class }) + JmxAutoConfiguration.class }) +// ,TraceSpringIntegrationAutoConfiguration.class, +// TraceWebSocketAutoConfiguration.class }) @Configuration public @interface DefaultTestAutoConfiguration { + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfigurationTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfigurationTest.java index 4af65dda6..523ddd2c6 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfigurationTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfigurationTest.java @@ -31,14 +31,15 @@ public class AsyncCustomAutoConfigurationTest { public void should_return_bean_when_its_not_a_async_configurer() throws Exception { AsyncCustomAutoConfiguration configuration = new AsyncCustomAutoConfiguration(); - Object bean = configuration - .postProcessAfterInitialization(new Object(), "someName"); + Object bean = configuration.postProcessAfterInitialization(new Object(), + "someName"); then(bean).isNotInstanceOf(LazyTraceAsyncCustomizer.class); } @Test - public void should_return_lazy_async_configurer_when_bean_is_async_configurer() throws Exception { + public void should_return_lazy_async_configurer_when_bean_is_async_configurer() + throws Exception { AsyncCustomAutoConfiguration configuration = new AsyncCustomAutoConfiguration(); Object bean = configuration @@ -46,4 +47,5 @@ public class AsyncCustomAutoConfigurationTest { then(bean).isInstanceOf(LazyTraceAsyncCustomizer.class); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessorTests.java index 454d8a94e..0873c58de 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessorTests.java @@ -46,13 +46,16 @@ import static org.assertj.core.api.BDDAssertions.thenThrownBy; @RunWith(MockitoJUnitRunner.class) public class ExecutorBeanPostProcessorTests { - @Mock BeanFactory beanFactory; + @Mock + BeanFactory beanFactory; + private SleuthAsyncProperties sleuthAsyncProperties; - + @Before public void setup() { this.sleuthAsyncProperties = new SleuthAsyncProperties(); - Mockito.when(beanFactory.getBean(SleuthAsyncProperties.class)).thenReturn(this.sleuthAsyncProperties); + Mockito.when(beanFactory.getBean(SleuthAsyncProperties.class)) + .thenReturn(this.sleuthAsyncProperties); } @Test @@ -65,9 +68,12 @@ public class ExecutorBeanPostProcessorTests { } class Foo implements Executor { - @Override public void execute(Runnable command) { + + @Override + public void execute(Runnable command) { } + } @Test @@ -83,23 +89,24 @@ public class ExecutorBeanPostProcessorTests { } @Test - public void should_throw_exception_when_it_is_not_possible_to_create_any_proxy() throws Exception { + public void should_throw_exception_when_it_is_not_possible_to_create_any_proxy() + throws Exception { ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); ExecutorBeanPostProcessor bpp = new ExecutorBeanPostProcessor(this.beanFactory) { - @Override Object createProxy(Object bean, boolean cglibProxy, - Executor executor) { + @Override + Object createProxy(Object bean, boolean cglibProxy, Executor executor) { throw new AopConfigException("foo"); } }; thenThrownBy(() -> bpp.postProcessAfterInitialization(service, "foo")) - .isInstanceOf(AopConfigException.class) - .hasMessage("foo"); + .isInstanceOf(AopConfigException.class).hasMessage("foo"); service.shutdown(); } @Test - public void should_create_a_cglib_proxy_by_default_for_ThreadPoolTaskExecutor() throws Exception { + public void should_create_a_cglib_proxy_by_default_for_ThreadPoolTaskExecutor() + throws Exception { Object o = new ExecutorBeanPostProcessor(this.beanFactory) .postProcessAfterInitialization(new FooThreadPoolTaskExecutor(), "foo"); @@ -108,45 +115,52 @@ public class ExecutorBeanPostProcessorTests { } class FooThreadPoolTaskExecutor extends ThreadPoolTaskExecutor { + } @Test - public void should_throw_exception_when_it_is_not_possible_to_create_any_proxyfor_ThreadPoolTaskExecutor() throws Exception { + public void should_throw_exception_when_it_is_not_possible_to_create_any_proxyfor_ThreadPoolTaskExecutor() + throws Exception { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); ExecutorBeanPostProcessor bpp = new ExecutorBeanPostProcessor(this.beanFactory) { - @Override Object createThreadPoolTaskExecutorProxy(Object bean, boolean cglibProxy, + @Override + Object createThreadPoolTaskExecutorProxy(Object bean, boolean cglibProxy, ThreadPoolTaskExecutor executor) { throw new AopConfigException("foo"); } }; thenThrownBy(() -> bpp.postProcessAfterInitialization(taskExecutor, "foo")) - .isInstanceOf(AopConfigException.class) - .hasMessage("foo"); + .isInstanceOf(AopConfigException.class).hasMessage("foo"); } - + @Test public void proxy_is_not_needed() throws Exception { - this.sleuthAsyncProperties.setIgnoredBeans(Collections.singletonList("fooExecutor")); - - boolean isProxyNeeded = new ExecutorBeanPostProcessor(this.beanFactory).isProxyNeeded("fooExecutor"); - + this.sleuthAsyncProperties + .setIgnoredBeans(Collections.singletonList("fooExecutor")); + + boolean isProxyNeeded = new ExecutorBeanPostProcessor(this.beanFactory) + .isProxyNeeded("fooExecutor"); + then(isProxyNeeded).isFalse(); } - + @Test public void proxy_is_needed() throws Exception { - boolean isProxyNeeded = new ExecutorBeanPostProcessor(this.beanFactory).isProxyNeeded("fooExecutor"); - + boolean isProxyNeeded = new ExecutorBeanPostProcessor(this.beanFactory) + .isProxyNeeded("fooExecutor"); + then(isProxyNeeded).isTrue(); } - + @Test public void should_not_create_proxy() throws Exception { - this.sleuthAsyncProperties.setIgnoredBeans(Collections.singletonList("fooExecutor")); - + this.sleuthAsyncProperties + .setIgnoredBeans(Collections.singletonList("fooExecutor")); + Object o = new ExecutorBeanPostProcessor(this.beanFactory) - .postProcessAfterInitialization(new ThreadPoolTaskExecutor(), "fooExecutor"); + .postProcessAfterInitialization(new ThreadPoolTaskExecutor(), + "fooExecutor"); then(o).isInstanceOf(ThreadPoolTaskExecutor.class); then(ClassUtils.isCglibProxy(o)).isFalse(); @@ -156,24 +170,27 @@ public class ExecutorBeanPostProcessorTests { public void should_throw_real_exception_when_using_proxy() throws Exception { // for LazyTraceExecutor Mockito.when(this.beanFactory.getBean(Tracing.class)) - .thenReturn(Tracing.newBuilder().build()); + .thenReturn(Tracing.newBuilder().build()); Mockito.when(this.beanFactory.getBean(SpanNamer.class)) - .thenReturn(new DefaultSpanNamer()); + .thenReturn(new DefaultSpanNamer()); Object o = new ExecutorBeanPostProcessor(this.beanFactory) - .postProcessAfterInitialization(new RejectedExecutionExecutor(), "fooExecutor"); + .postProcessAfterInitialization(new RejectedExecutionExecutor(), + "fooExecutor"); then(o).isInstanceOf(RejectedExecutionExecutor.class); then(ClassUtils.isCglibProxy(o)).isTrue(); - thenThrownBy(() -> ((RejectedExecutionExecutor) o).execute(() -> {})) - .isInstanceOf(RejectedExecutionException.class) - .hasMessage("rejected"); + thenThrownBy(() -> ((RejectedExecutionExecutor) o).execute(() -> { + })).isInstanceOf(RejectedExecutionException.class).hasMessage("rejected"); } class RejectedExecutionExecutor implements Executor { - @Override public void execute(Runnable task) { + + @Override + public void execute(Runnable task) { throw new RejectedExecutionException("rejected"); } + } } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizerTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizerTest.java index 0552ecb70..c6fc6f8b8 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizerTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizerTest.java @@ -34,9 +34,14 @@ import static org.assertj.core.api.BDDAssertions.then; @RunWith(MockitoJUnitRunner.class) public class LazyTraceAsyncCustomizerTest { - @Mock BeanFactory beanFactory; - @Mock AsyncConfigurer asyncConfigurer; - @InjectMocks LazyTraceAsyncCustomizer lazyTraceAsyncCustomizer; + @Mock + BeanFactory beanFactory; + + @Mock + AsyncConfigurer asyncConfigurer; + + @InjectMocks + LazyTraceAsyncCustomizer lazyTraceAsyncCustomizer; @Test public void should_wrap_async_executor_in_trace_version() throws Exception { @@ -44,4 +49,5 @@ public class LazyTraceAsyncCustomizerTest { then(executor).isExactlyInstanceOf(LazyTraceExecutor.class); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncAspectTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncAspectTest.java index 1612ea447..29648f764 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncAspectTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncAspectTest.java @@ -19,28 +19,31 @@ import org.springframework.cloud.sleuth.util.ArrayListSpanReporter; public class TraceAsyncAspectTest { ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + ProceedingJoinPoint point = Mockito.mock(ProceedingJoinPoint.class); @Before public void setup() throws NoSuchMethodException { MethodSignature signature = Mockito.mock(MethodSignature.class); BDDMockito.given(signature.getName()).willReturn("fooBar"); - BDDMockito.given(signature.getMethod()).willReturn(TraceAsyncAspectTest.class.getMethod("setup")); + BDDMockito.given(signature.getMethod()) + .willReturn(TraceAsyncAspectTest.class.getMethod("setup")); BDDMockito.given(this.point.getSignature()).willReturn(signature); BDDMockito.given(this.point.getTarget()).willReturn(""); } - //Issue#926 - @Test public void should_work() throws Throwable { + // Issue#926 + @Test + public void should_work() throws Throwable { TraceAsyncAspect asyncAspect = new TraceAsyncAspect(this.tracing.tracer(), new DefaultSpanNamer()) { - @Override String name(ProceedingJoinPoint pjp) { + @Override + String name(ProceedingJoinPoint pjp) { return "foo-bar"; } }; @@ -51,4 +54,5 @@ public class TraceAsyncAspectTest { BDDAssertions.then(this.reporter.getSpans().get(0).name()).isEqualTo("foo-bar"); BDDAssertions.then(this.reporter.getSpans().get(0).timestamp()).isPositive(); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncIntegrationTests.java index 313db2368..def16c789 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncIntegrationTests.java @@ -50,8 +50,10 @@ public class TraceAsyncIntegrationTests { @Autowired ClassPerformingAsyncLogic classPerformingAsyncLogic; - @Autowired + + @Autowired Tracing tracer; + @Autowired ArrayListSpanReporter reporter; @@ -83,7 +85,8 @@ public class TraceAsyncIntegrationTests { whenAsyncProcessingTakesPlace(); thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOne(span); - } finally { + } + finally { span.finish(); } } @@ -95,8 +98,10 @@ public class TraceAsyncIntegrationTests { try (Tracer.SpanInScope ws = this.tracer.tracer().withSpanInScope(span.start())) { whenAsyncProcessingTakesPlaceWithCustomSpanName(); - thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName(span); - } finally { + thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName( + span); + } + finally { span.finish(); } } @@ -114,65 +119,72 @@ public class TraceAsyncIntegrationTests { } private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOne(final Span span) { - Awaitility.await().atMost(5, SECONDS).untilAsserted( - () -> { - Span asyncSpan = TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan(); - then(asyncSpan.context().traceId()).isEqualTo(span.context().traceId()); - List spans = TraceAsyncIntegrationTests.this.reporter - .getSpans(); - then(spans).hasSize(1); - zipkin2.Span reportedAsyncSpan = spans.get(0); - then(reportedAsyncSpan.traceId()).isEqualTo(span.context().traceIdString()); - then(reportedAsyncSpan.name()).isEqualTo("invoke-asynchronous-logic"); - then(reportedAsyncSpan.tags()) - .contains(new AbstractMap.SimpleEntry<>("class", "ClassPerformingAsyncLogic")) - .contains(new AbstractMap.SimpleEntry<>("method", "invokeAsynchronousLogic")); - }); + Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> { + Span asyncSpan = TraceAsyncIntegrationTests.this.classPerformingAsyncLogic + .getSpan(); + then(asyncSpan.context().traceId()).isEqualTo(span.context().traceId()); + List spans = TraceAsyncIntegrationTests.this.reporter + .getSpans(); + then(spans).hasSize(1); + zipkin2.Span reportedAsyncSpan = spans.get(0); + then(reportedAsyncSpan.traceId()).isEqualTo(span.context().traceIdString()); + then(reportedAsyncSpan.name()).isEqualTo("invoke-asynchronous-logic"); + then(reportedAsyncSpan.tags()) + .contains(new AbstractMap.SimpleEntry<>("class", + "ClassPerformingAsyncLogic")) + .contains(new AbstractMap.SimpleEntry<>("method", + "invokeAsynchronousLogic")); + }); } private void thenANewAsyncSpanGetsCreated() { - Awaitility.await().atMost(5, SECONDS).untilAsserted( - () -> { - List spans = TraceAsyncIntegrationTests.this.reporter - .getSpans(); - then(spans).hasSize(1); - zipkin2.Span reportedAsyncSpan = spans.get(0); - then(reportedAsyncSpan.name()).isEqualTo("invoke-asynchronous-logic"); - then(reportedAsyncSpan.tags()) - .contains(new AbstractMap.SimpleEntry<>("class", "ClassPerformingAsyncLogic")) - .contains(new AbstractMap.SimpleEntry<>("method", "invokeAsynchronousLogic")); - }); + Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> { + List spans = TraceAsyncIntegrationTests.this.reporter + .getSpans(); + then(spans).hasSize(1); + zipkin2.Span reportedAsyncSpan = spans.get(0); + then(reportedAsyncSpan.name()).isEqualTo("invoke-asynchronous-logic"); + then(reportedAsyncSpan.tags()) + .contains(new AbstractMap.SimpleEntry<>("class", + "ClassPerformingAsyncLogic")) + .contains(new AbstractMap.SimpleEntry<>("method", + "invokeAsynchronousLogic")); + }); } - private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName(final Span span) { - Awaitility.await().atMost(5, SECONDS).untilAsserted( - () -> { - Span asyncSpan = TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan(); - then(asyncSpan.context().traceId()).isEqualTo(span.context().traceId()); - List spans = TraceAsyncIntegrationTests.this.reporter - .getSpans(); - then(spans).hasSize(1); - zipkin2.Span reportedAsyncSpan = spans.get(0); - then(reportedAsyncSpan.traceId()).isEqualTo(span.context().traceIdString()); - then(reportedAsyncSpan.name()).isEqualTo("foo"); - then(reportedAsyncSpan.tags()) - .contains(new AbstractMap.SimpleEntry<>("class", "ClassPerformingAsyncLogic")) - .contains(new AbstractMap.SimpleEntry<>("method", "customNameInvokeAsynchronousLogic")); - }); + private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName( + final Span span) { + Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> { + Span asyncSpan = TraceAsyncIntegrationTests.this.classPerformingAsyncLogic + .getSpan(); + then(asyncSpan.context().traceId()).isEqualTo(span.context().traceId()); + List spans = TraceAsyncIntegrationTests.this.reporter + .getSpans(); + then(spans).hasSize(1); + zipkin2.Span reportedAsyncSpan = spans.get(0); + then(reportedAsyncSpan.traceId()).isEqualTo(span.context().traceIdString()); + then(reportedAsyncSpan.name()).isEqualTo("foo"); + then(reportedAsyncSpan.tags()) + .contains(new AbstractMap.SimpleEntry<>("class", + "ClassPerformingAsyncLogic")) + .contains(new AbstractMap.SimpleEntry<>("method", + "customNameInvokeAsynchronousLogic")); + }); } private void thenAsyncSpanHasCustomName() { - Awaitility.await().atMost(5, SECONDS).untilAsserted( - () -> { - List spans = TraceAsyncIntegrationTests.this.reporter - .getSpans(); - then(spans).hasSize(1); - zipkin2.Span reportedAsyncSpan = spans.get(0); - then(reportedAsyncSpan.name()).isEqualTo("foo"); - then(reportedAsyncSpan.tags()) - .contains(new AbstractMap.SimpleEntry<>("class", "ClassPerformingAsyncLogic")) - .contains(new AbstractMap.SimpleEntry<>("method", "customNameInvokeAsynchronousLogic")); - }); + Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> { + List spans = TraceAsyncIntegrationTests.this.reporter + .getSpans(); + then(spans).hasSize(1); + zipkin2.Span reportedAsyncSpan = spans.get(0); + then(reportedAsyncSpan.name()).isEqualTo("foo"); + then(reportedAsyncSpan.tags()) + .contains(new AbstractMap.SimpleEntry<>("class", + "ClassPerformingAsyncLogic")) + .contains(new AbstractMap.SimpleEntry<>("method", + "customNameInvokeAsynchronousLogic")); + }); } @DefaultTestAutoConfiguration @@ -185,7 +197,8 @@ public class TraceAsyncIntegrationTests { return new ClassPerformingAsyncLogic(tracer); } - @Bean Sampler defaultSampler() { + @Bean + Sampler defaultSampler() { return Sampler.ALWAYS_SAMPLE; } @@ -224,5 +237,7 @@ public class TraceAsyncIntegrationTests { public void clear() { this.span.set(null); } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncListenableTaskExecutorTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncListenableTaskExecutorTest.java index 14aa0baf4..ce1f3a399 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncListenableTaskExecutorTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncListenableTaskExecutorTest.java @@ -37,12 +37,14 @@ import org.springframework.core.task.SimpleAsyncTaskExecutor; public class TraceAsyncListenableTaskExecutorTest { AsyncListenableTaskExecutor delegate = new SimpleAsyncTaskExecutor(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) + .addScopeDecorator(StrictScopeDecorator.create()).build()) .build(); + Tracer tracer = this.tracing.tracer(); + TraceAsyncListenableTaskExecutor traceAsyncListenableTaskExecutor = new TraceAsyncListenableTaskExecutor( this.delegate, this.tracing); @@ -51,9 +53,11 @@ public class TraceAsyncListenableTaskExecutorTest { AtomicBoolean executed = new AtomicBoolean(); Span span = this.tracer.nextSpan().name("foo"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { - this.traceAsyncListenableTaskExecutor.submitListenable(aRunnable(this.tracing, executed)).get(); - } finally { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + this.traceAsyncListenableTaskExecutor + .submitListenable(aRunnable(this.tracing, executed)).get(); + } + finally { span.finish(); } @@ -65,10 +69,11 @@ public class TraceAsyncListenableTaskExecutorTest { Span span = this.tracer.nextSpan().name("foo"); Span spanFromListenable; - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { spanFromListenable = this.traceAsyncListenableTaskExecutor .submitListenable(aCallable(this.tracing)).get(); - } finally { + } + finally { span.finish(); } @@ -80,16 +85,17 @@ public class TraceAsyncListenableTaskExecutorTest { AtomicBoolean executed = new AtomicBoolean(); Span span = this.tracer.nextSpan().name("foo"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { - this.traceAsyncListenableTaskExecutor.execute(aRunnable(this.tracing, executed)); - } finally { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + this.traceAsyncListenableTaskExecutor + .execute(aRunnable(this.tracing, executed)); + } + finally { span.finish(); } - Awaitility.await().atMost(5, TimeUnit.SECONDS) - .untilAsserted(() -> { - BDDAssertions.then(executed.get()).isTrue(); - }); + Awaitility.await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> { + BDDAssertions.then(executed.get()).isTrue(); + }); } @Test @@ -97,16 +103,17 @@ public class TraceAsyncListenableTaskExecutorTest { AtomicBoolean executed = new AtomicBoolean(); Span span = this.tracer.nextSpan().name("foo"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { - this.traceAsyncListenableTaskExecutor.execute(aRunnable(this.tracing, executed), 1L); - } finally { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + this.traceAsyncListenableTaskExecutor + .execute(aRunnable(this.tracing, executed), 1L); + } + finally { span.finish(); } - Awaitility.await().atMost(5, TimeUnit.SECONDS) - .untilAsserted(() -> { - BDDAssertions.then(executed.get()).isTrue(); - }); + Awaitility.await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> { + BDDAssertions.then(executed.get()).isTrue(); + }); } @Test @@ -114,10 +121,11 @@ public class TraceAsyncListenableTaskExecutorTest { Span span = this.tracer.nextSpan().name("foo"); Span spanFromListenable; - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { spanFromListenable = this.traceAsyncListenableTaskExecutor .submit(aCallable(this.tracing)).get(); - } finally { + } + finally { span.finish(); } @@ -129,16 +137,17 @@ public class TraceAsyncListenableTaskExecutorTest { AtomicBoolean executed = new AtomicBoolean(); Span span = this.tracer.nextSpan().name("foo"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { - this.traceAsyncListenableTaskExecutor.submit(aRunnable(this.tracing, executed)).get(); - } finally { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + this.traceAsyncListenableTaskExecutor + .submit(aRunnable(this.tracing, executed)).get(); + } + finally { span.finish(); } - Awaitility.await().atMost(5, TimeUnit.SECONDS) - .untilAsserted(() -> { - BDDAssertions.then(executed.get()).isTrue(); - }); + Awaitility.await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> { + BDDAssertions.then(executed.get()).isTrue(); + }); } Runnable aRunnable(Tracing tracing, AtomicBoolean executed) { @@ -151,4 +160,5 @@ public class TraceAsyncListenableTaskExecutorTest { Callable aCallable(Tracing tracing) { return () -> tracing.tracer().currentSpan(); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceCallableTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceCallableTests.java index f8338430a..d65ec7a70 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceCallableTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceCallableTests.java @@ -39,13 +39,14 @@ import static org.assertj.core.api.BDDAssertions.then; public class TraceCallableTests { ExecutorService executor = Executors.newSingleThreadExecutor(); + ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + Tracer tracer = this.tracing.tracer(); @After @@ -56,16 +57,12 @@ public class TraceCallableTests { } @Test - public void should_not_see_same_trace_id_in_successive_tasks() - throws Exception { - Span firstSpan = givenCallableGetsSubmitted( - thatRetrievesTraceFromThreadLocal()); + public void should_not_see_same_trace_id_in_successive_tasks() throws Exception { + Span firstSpan = givenCallableGetsSubmitted(thatRetrievesTraceFromThreadLocal()); - Span secondSpan = whenCallableGetsSubmitted( - thatRetrievesTraceFromThreadLocal()); + Span secondSpan = whenCallableGetsSubmitted(thatRetrievesTraceFromThreadLocal()); - then(secondSpan.context().traceId()) - .isNotEqualTo(firstSpan.context().traceId()); + then(secondSpan.context().traceId()).isNotEqualTo(firstSpan.context().traceId()); } @Test @@ -83,7 +80,7 @@ public class TraceCallableTests { public void should_remove_parent_span_from_thread_local_after_finishing_work() throws Exception { Span parent = this.tracer.nextSpan().name("http:parent"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(parent)){ + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(parent)) { Span child = givenCallableGetsSubmitted(thatRetrievesTraceFromThreadLocal()); then(parent).as("parent").isNotNull(); then(child.context().parentId()).isEqualTo(parent.context().spanId()); @@ -97,22 +94,22 @@ public class TraceCallableTests { } @Test - public void should_take_name_of_span_from_span_name_annotation() - throws Exception { + public void should_take_name_of_span_from_span_name_annotation() throws Exception { whenATraceKeepingCallableGetsSubmitted(); then(this.reporter.getSpans()).hasSize(1); - then(this.reporter.getSpans().get(0).name()).isEqualTo("some-callable-name-from-annotation"); + then(this.reporter.getSpans().get(0).name()) + .isEqualTo("some-callable-name-from-annotation"); } @Test public void should_take_name_of_span_from_to_string_if_span_name_annotation_is_missing() throws Exception { - whenCallableGetsSubmitted( - thatRetrievesTraceFromThreadLocal()); + whenCallableGetsSubmitted(thatRetrievesTraceFromThreadLocal()); then(this.reporter.getSpans()).hasSize(1); - then(this.reporter.getSpans().get(0).name()).isEqualTo("some-callable-name-from-to-string"); + then(this.reporter.getSpans().get(0).name()) + .isEqualTo("some-callable-name-from-to-string"); } private Callable thatRetrievesTraceFromThreadLocal() { @@ -136,13 +133,15 @@ public class TraceCallableTests { private Span whenCallableGetsSubmitted(Callable callable) throws InterruptedException, java.util.concurrent.ExecutionException { - return this.executor.submit(new TraceCallable<>(this.tracing, new DefaultSpanNamer(), - callable)).get(); + return this.executor.submit( + new TraceCallable<>(this.tracing, new DefaultSpanNamer(), callable)) + .get(); } + private Span whenATraceKeepingCallableGetsSubmitted() throws InterruptedException, java.util.concurrent.ExecutionException { - return this.executor.submit(new TraceCallable<>(this.tracing, new DefaultSpanNamer(), - new TraceKeepingCallable())).get(); + return this.executor.submit(new TraceCallable<>(this.tracing, + new DefaultSpanNamer(), new TraceKeepingCallable())).get(); } private Span whenNonTraceableCallableGetsSubmitted(Callable callable) @@ -152,6 +151,7 @@ public class TraceCallableTests { @SpanName("some-callable-name-from-annotation") static class TraceKeepingCallable implements Callable { + public Span span; @Override @@ -159,6 +159,7 @@ public class TraceCallableTests { this.span = Tracing.currentTracer().currentSpan(); return this.span; } + } } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceRunnableTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceRunnableTests.java index 3f049ac64..d1dd1efa0 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceRunnableTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceRunnableTests.java @@ -39,13 +39,14 @@ import static org.assertj.core.api.BDDAssertions.then; public class TraceRunnableTests { ExecutorService executor = Executors.newSingleThreadExecutor(); + ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + Tracer tracer = this.tracing.tracer(); @After @@ -95,14 +96,14 @@ public class TraceRunnableTests { } @Test - public void should_take_name_of_span_from_span_name_annotation() - throws Exception { + public void should_take_name_of_span_from_span_name_annotation() throws Exception { TraceKeepingRunnable traceKeepingRunnable = runnableThatRetrievesTraceFromThreadLocal(); whenRunnableGetsSubmitted(traceKeepingRunnable); then(this.reporter.getSpans()).hasSize(1); - then(this.reporter.getSpans().get(0).name()).isEqualTo("some-runnable-name-from-annotation"); + then(this.reporter.getSpans().get(0).name()) + .isEqualTo("some-runnable-name-from-annotation"); } @Test @@ -114,7 +115,8 @@ public class TraceRunnableTests { whenRunnableGetsSubmitted(runnable); then(this.reporter.getSpans()).hasSize(1); - then(this.reporter.getSpans().get(0).name()).isEqualTo("some-runnable-name-from-to-string"); + then(this.reporter.getSpans().get(0).name()) + .isEqualTo("some-runnable-name-from-to-string"); } private TraceKeepingRunnable runnableThatRetrievesTraceFromThreadLocal() { @@ -126,8 +128,9 @@ public class TraceRunnableTests { } private void whenRunnableGetsSubmitted(Runnable runnable) throws Exception { - this.executor.submit(new TraceRunnable(this.tracing, new DefaultSpanNamer(), - runnable)).get(); + this.executor + .submit(new TraceRunnable(this.tracing, new DefaultSpanNamer(), runnable)) + .get(); } private void whenNonTraceableRunnableGetsSubmitted(Runnable runnable) @@ -142,7 +145,8 @@ public class TraceRunnableTests { span.set(tracer.currentSpan()); } - @Override public String toString() { + @Override + public String toString() { return "some-runnable-name-from-to-string"; } }; @@ -163,6 +167,7 @@ public class TraceRunnableTests { public void run() { this.span = this.tracer.currentSpan(); } + } } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorServiceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorServiceTests.java index 14194867e..b45d84a8f 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorServiceTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorServiceTests.java @@ -54,24 +54,31 @@ import static org.assertj.core.api.BDDAssertions.then; @RunWith(MockitoJUnitRunner.class) public class TraceableExecutorServiceTests { + private static int TOTAL_THREADS = 10; - @Mock BeanFactory beanFactory; + @Mock + BeanFactory beanFactory; + ExecutorService executorService = Executors.newFixedThreadPool(3); + ExecutorService traceManagerableExecutorService; + ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + Tracer tracer = this.tracing.tracer(); + SpanVerifyingRunnable spanVerifyingRunnable = new SpanVerifyingRunnable(); @Before public void setup() { - this.traceManagerableExecutorService = new TraceableExecutorService(beanFactory(), this.executorService); + this.traceManagerableExecutorService = new TraceableExecutorService(beanFactory(), + this.executorService); this.reporter.clear(); this.spanVerifyingRunnable.clear(); } @@ -90,49 +97,54 @@ public class TraceableExecutorServiceTests { throws Exception { ScopedSpan span = this.tracer.startScopedSpan("http:PARENT"); try { - CompletableFuture.allOf(runnablesExecutedViaTraceManagerableExecutorService()).get(); - } finally { + CompletableFuture.allOf(runnablesExecutedViaTraceManagerableExecutorService()) + .get(); + } + finally { span.finish(); } - then(this.spanVerifyingRunnable.traceIds.stream().distinct() - .collect(toList())).hasSize(1); - then(this.spanVerifyingRunnable.spanIds.stream().distinct() - .collect(toList())).hasSize(TOTAL_THREADS); + then(this.spanVerifyingRunnable.traceIds.stream().distinct().collect(toList())) + .hasSize(1); + then(this.spanVerifyingRunnable.spanIds.stream().distinct().collect(toList())) + .hasSize(TOTAL_THREADS); } @Test @SuppressWarnings("unchecked") - public void should_wrap_methods_in_trace_representation_only_for_non_tracing_callables() throws Exception { + public void should_wrap_methods_in_trace_representation_only_for_non_tracing_callables() + throws Exception { ExecutorService executorService = Mockito.mock(ExecutorService.class); - TraceableExecutorService traceExecutorService = new TraceableExecutorService(beanFactory(), executorService); + TraceableExecutorService traceExecutorService = new TraceableExecutorService( + beanFactory(), executorService); traceExecutorService.invokeAll(callables()); - BDDMockito.then(executorService).should().invokeAll(BDDMockito.argThat( - withSpanContinuingTraceCallablesOnly())); + BDDMockito.then(executorService).should() + .invokeAll(BDDMockito.argThat(withSpanContinuingTraceCallablesOnly())); traceExecutorService.invokeAll(callables(), 1L, TimeUnit.DAYS); - BDDMockito.then(executorService).should().invokeAll(BDDMockito.argThat( - withSpanContinuingTraceCallablesOnly()), - BDDMockito.eq(1L) , BDDMockito.eq(TimeUnit.DAYS)); + BDDMockito.then(executorService).should().invokeAll( + BDDMockito.argThat(withSpanContinuingTraceCallablesOnly()), + BDDMockito.eq(1L), BDDMockito.eq(TimeUnit.DAYS)); traceExecutorService.invokeAny(callables()); - BDDMockito.then(executorService).should().invokeAny(BDDMockito.argThat( - withSpanContinuingTraceCallablesOnly())); + BDDMockito.then(executorService).should() + .invokeAny(BDDMockito.argThat(withSpanContinuingTraceCallablesOnly())); traceExecutorService.invokeAny(callables(), 1L, TimeUnit.DAYS); - BDDMockito.then(executorService).should().invokeAny(BDDMockito.argThat( - withSpanContinuingTraceCallablesOnly()), - BDDMockito.eq(1L) , BDDMockito.eq(TimeUnit.DAYS)); + BDDMockito.then(executorService).should().invokeAny( + BDDMockito.argThat(withSpanContinuingTraceCallablesOnly()), + BDDMockito.eq(1L), BDDMockito.eq(TimeUnit.DAYS)); } private ArgumentMatcher>> withSpanContinuingTraceCallablesOnly() { return argument -> { try { - BDDAssertions.then(argument) - .flatExtracting(Object::getClass) - .containsOnlyElementsOf(Collections.singletonList(TraceCallable.class)); - } catch (AssertionError e) { + BDDAssertions.then(argument).flatExtracting(Object::getClass) + .containsOnlyElementsOf( + Collections.singletonList(TraceCallable.class)); + } + catch (AssertionError e) { return false; } return true; @@ -147,7 +159,8 @@ public class TraceableExecutorServiceTests { } @Test - public void should_propagate_trace_info_when_compleable_future_is_used() throws Exception { + public void should_propagate_trace_info_when_compleable_future_is_used() + throws Exception { ExecutorService executorService = this.executorService; BeanFactory beanFactory = beanFactory(); // tag::completablefuture[] @@ -166,20 +179,24 @@ public class TraceableExecutorServiceTests { private CompletableFuture[] runnablesExecutedViaTraceManagerableExecutorService() { List> futures = new ArrayList<>(); for (int i = 0; i < TOTAL_THREADS; i++) { - futures.add(CompletableFuture.runAsync(this.spanVerifyingRunnable, this.traceManagerableExecutorService)); + futures.add(CompletableFuture.runAsync(this.spanVerifyingRunnable, + this.traceManagerableExecutorService)); } return futures.toArray(new CompletableFuture[futures.size()]); } - + BeanFactory beanFactory() { - BDDMockito.given(this.beanFactory.getBean(Tracing.class)).willReturn(this.tracing); - BDDMockito.given(this.beanFactory.getBean(SpanNamer.class)).willReturn(new DefaultSpanNamer()); + BDDMockito.given(this.beanFactory.getBean(Tracing.class)) + .willReturn(this.tracing); + BDDMockito.given(this.beanFactory.getBean(SpanNamer.class)) + .willReturn(new DefaultSpanNamer()); return this.beanFactory; } class SpanVerifyingRunnable implements Runnable { Queue traceIds = new ConcurrentLinkedQueue<>(); + Queue spanIds = new ConcurrentLinkedQueue<>(); @Override @@ -193,6 +210,7 @@ public class TraceableExecutorServiceTests { this.traceIds.clear(); this.spanIds.clear(); } + } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceableScheduledExecutorServiceTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceableScheduledExecutorServiceTest.java index 5c1e82f83..ce5cd8f02 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceableScheduledExecutorServiceTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/TraceableScheduledExecutorServiceTest.java @@ -48,13 +48,15 @@ public class TraceableScheduledExecutorServiceTest { Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) + .addScopeDecorator(StrictScopeDecorator.create()).build()) .build(); + @Mock BeanFactory beanFactory; + @Mock ScheduledExecutorService scheduledExecutorService; + @InjectMocks TraceableScheduledExecutorService traceableScheduledExecutorService; @@ -78,30 +80,30 @@ public class TraceableScheduledExecutorServiceTest { this.traceableScheduledExecutorService.schedule(aCallable(), 1L, TimeUnit.DAYS); then(this.scheduledExecutorService).should().schedule( - BDDMockito.argThat(matcher(Callable.class, - instanceOf(TraceCallable.class))), + BDDMockito.argThat( + matcher(Callable.class, instanceOf(TraceCallable.class))), anyLong(), any(TimeUnit.class)); } @Test - public void should_schedule_at_fixed_rate_a_trace_runnable() - throws Exception { + public void should_schedule_at_fixed_rate_a_trace_runnable() throws Exception { this.traceableScheduledExecutorService.scheduleAtFixedRate(aRunnable(), 1L, 1L, TimeUnit.DAYS); then(this.scheduledExecutorService).should().scheduleAtFixedRate( - BDDMockito.argThat(matcher(Runnable.class, instanceOf(TraceRunnable.class))), + BDDMockito.argThat( + matcher(Runnable.class, instanceOf(TraceRunnable.class))), anyLong(), anyLong(), any(TimeUnit.class)); } @Test - public void should_schedule_with_fixed_delay_a_trace_runnable() - throws Exception { + public void should_schedule_with_fixed_delay_a_trace_runnable() throws Exception { this.traceableScheduledExecutorService.scheduleWithFixedDelay(aRunnable(), 1L, 1L, TimeUnit.DAYS); then(this.scheduledExecutorService).should().scheduleWithFixedDelay( - BDDMockito.argThat(matcher(Runnable.class, instanceOf(TraceRunnable.class))), + BDDMockito.argThat( + matcher(Runnable.class, instanceOf(TraceRunnable.class))), anyLong(), anyLong(), any(TimeUnit.class)); } @@ -123,8 +125,11 @@ public class TraceableScheduledExecutorServiceTest { } BeanFactory beanFactory() { - BDDMockito.given(this.beanFactory.getBean(Tracing.class)).willReturn(this.tracing); - BDDMockito.given(this.beanFactory.getBean(SpanNamer.class)).willReturn(new DefaultSpanNamer()); + BDDMockito.given(this.beanFactory.getBean(Tracing.class)) + .willReturn(this.tracing); + BDDMockito.given(this.beanFactory.getBean(SpanNamer.class)) + .willReturn(new DefaultSpanNamer()); return this.beanFactory; } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue410/Issue410Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue410/Issue410Tests.java index 2642144c7..e610026be 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue410/Issue410Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue410/Issue410Tests.java @@ -63,10 +63,18 @@ public class Issue410Tests { private static final Log log = LogFactory .getLog(MethodHandles.lookup().lookupClass()); - @Autowired Environment environment; - @Autowired Tracer tracer; - @Autowired AsyncTask asyncTask; - @Autowired RestTemplate restTemplate; + @Autowired + Environment environment; + + @Autowired + Tracer tracer; + + @Autowired + AsyncTask asyncTask; + + @Autowired + RestTemplate restTemplate; + /** * Related to issue #445 */ @@ -77,7 +85,7 @@ public class Issue410Tests { public void should_pass_tracing_info_for_tasks_running_without_a_pool() { Span span = this.tracer.nextSpan().name("foo"); log.info("Starting test"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { String response = this.restTemplate.getForObject( "http://localhost:" + port() + "/without_pool", String.class); @@ -99,7 +107,7 @@ public class Issue410Tests { public void should_pass_tracing_info_for_tasks_running_with_a_pool() { Span span = this.tracer.nextSpan().name("foo"); log.info("Starting test"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { String response = this.restTemplate.getForObject( "http://localhost:" + port() + "/with_pool", String.class); @@ -124,7 +132,7 @@ public class Issue410Tests { public void should_pass_tracing_info_for_completable_futures_with_executor() { Span span = this.tracer.nextSpan().name("foo"); log.info("Starting test"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { String response = this.restTemplate.getForObject( "http://localhost:" + port() + "/completable", String.class); @@ -149,7 +157,7 @@ public class Issue410Tests { public void should_pass_tracing_info_for_completable_futures_with_task_scheduler() { Span span = this.tracer.nextSpan().name("foo"); log.info("Starting test"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { String response = this.restTemplate.getForObject( "http://localhost:" + port() + "/taskScheduler", String.class); @@ -170,6 +178,7 @@ public class Issue410Tests { private int port() { return this.environment.getProperty("local.server.port", Integer.class); } + } @Configuration @@ -198,19 +207,21 @@ class AppConfig { @Component class AsyncTask { - private static final Log log = LogFactory.getLog( - AsyncTask.class); + private static final Log log = LogFactory.getLog(AsyncTask.class); private AtomicReference span = new AtomicReference<>(); - @Autowired + @Autowired Tracer tracer; + @Autowired @Qualifier("poolTaskExecutor") Executor executor; + @Autowired @Qualifier("taskScheduler") Executor taskScheduler; + @Autowired BeanFactory beanFactory; @@ -242,7 +253,8 @@ class AsyncTask { Span joinedSpan1 = span1.join(); Span joinedSpan2 = span2.join(); then(joinedSpan2).isNotNull(); - then(joinedSpan1.context().traceId()).isEqualTo(joinedSpan2.context().traceId()); + then(joinedSpan1.context().traceId()) + .isEqualTo(joinedSpan2.context().traceId()); AsyncTask.log.info("TraceIds are correct"); return joinedSpan2; }); @@ -255,14 +267,12 @@ class AsyncTask { CompletableFuture span1 = CompletableFuture.supplyAsync(() -> { AsyncTask.log.info("First completable future"); return AsyncTask.this.tracer.currentSpan(); - }, new LazyTraceExecutor( - AsyncTask.this.beanFactory, + }, new LazyTraceExecutor(AsyncTask.this.beanFactory, AsyncTask.this.taskScheduler)); CompletableFuture span2 = CompletableFuture.supplyAsync(() -> { AsyncTask.log.info("Second completable future"); return AsyncTask.this.tracer.currentSpan(); - }, new LazyTraceExecutor( - AsyncTask.this.beanFactory, + }, new LazyTraceExecutor(AsyncTask.this.beanFactory, AsyncTask.this.taskScheduler)); CompletableFuture response = CompletableFuture.allOf(span1, span2) .thenApply(ignoredVoid -> { @@ -270,7 +280,8 @@ class AsyncTask { Span joinedSpan1 = span1.join(); Span joinedSpan2 = span2.join(); then(joinedSpan2).isNotNull(); - then(joinedSpan1.context().traceId()).isEqualTo(joinedSpan2.context().traceId()); + then(joinedSpan1.context().traceId()) + .isEqualTo(joinedSpan2.context().traceId()); AsyncTask.log.info("TraceIds are correct"); return joinedSpan2; }); @@ -281,17 +292,20 @@ class AsyncTask { public AtomicReference getSpan() { return span; } + } @SpringBootApplication(exclude = SpringDataWebAutoConfiguration.class) @RestController class Application { - private static final Log log = LogFactory.getLog( - Application.class); + private static final Log log = LogFactory.getLog(Application.class); - @Autowired AsyncTask asyncTask; - @Autowired Tracer tracer; + @Autowired + AsyncTask asyncTask; + + @Autowired + Tracer tracer; @RequestMapping("/with_pool") public String withPool() { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue546/Issue546Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue546/Issue546Tests.java index f74aba1ad..3066c1cc2 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue546/Issue546Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue546/Issue546Tests.java @@ -44,23 +44,25 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = Issue546TestsApp.class, - properties = {"ribbon.eureka.enabled=false", "feign.hystrix.enabled=false", "server.port=0"}, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(classes = Issue546TestsApp.class, properties = { + "ribbon.eureka.enabled=false", "feign.hystrix.enabled=false", + "server.port=0" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class Issue546Tests { - @Autowired Environment environment; + @Autowired + Environment environment; @Test public void should_pass_tracing_info_when_using_callbacks() { - new RestTemplate() - .getForObject("http://localhost:" + port() + "/trace-async-rest-template", - String.class); + new RestTemplate().getForObject( + "http://localhost:" + port() + "/trace-async-rest-template", + String.class); } private int port() { return this.environment.getProperty("local.server.port", Integer.class); } + } @SpringBootApplication @@ -75,9 +77,12 @@ class Issue546TestsApp { @RestController class Controller { - private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + + private static final Log log = LogFactory + .getLog(MethodHandles.lookup().lookupClass()); private final AsyncRestTemplate traceAsyncRestTemplate; + private final Tracing tracer; public Controller(AsyncRestTemplate traceAsyncRestTemplate, Tracing tracer) { @@ -85,9 +90,11 @@ class Controller { this.tracer = tracer; } - @Value("${server.port}") private String port; + @Value("${server.port}") + private String port; - @RequestMapping(value = "/bean") public HogeBean bean() { + @RequestMapping(value = "/bean") + public HogeBean bean() { log.info("(/bean) I got a request!"); return new HogeBean("test", 18); } @@ -120,7 +127,9 @@ class Controller { } class HogeBean { + private String name; + private int age; public HogeBean(String name, int age) { @@ -143,4 +152,5 @@ class HogeBean { public void setAge(int age) { this.age = age; } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/HystrixAnnotationsIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/HystrixAnnotationsIntegrationTests.java index f29bc85a6..af014d29d 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/HystrixAnnotationsIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/HystrixAnnotationsIntegrationTests.java @@ -48,6 +48,7 @@ public class HystrixAnnotationsIntegrationTests { @Autowired HystrixCommandInvocationSpanCatcher catcher; + @Autowired Tracing tracer; @@ -71,9 +72,9 @@ public class HystrixAnnotationsIntegrationTests { private void thenSpanInHystrixThreadIsContinued(final Span span) { then(span).isNotNull(); Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> { - then(HystrixAnnotationsIntegrationTests.this.catcher).isNotNull(); - then(span.context().traceId()) - .isEqualTo(HystrixAnnotationsIntegrationTests.this.catcher.getTraceId()); + then(HystrixAnnotationsIntegrationTests.this.catcher).isNotNull(); + then(span.context().traceId()).isEqualTo( + HystrixAnnotationsIntegrationTests.this.catcher.getTraceId()); }); } @@ -103,6 +104,7 @@ public class HystrixAnnotationsIntegrationTests { public static class HystrixCommandInvocationSpanCatcher { AtomicReference spanCaughtFromHystrixThread; + private final Tracing tracing; public HystrixCommandInvocationSpanCatcher(Tracing tracing) { @@ -126,5 +128,7 @@ public class HystrixAnnotationsIntegrationTests { public Span getSpan() { return this.spanCaughtFromHystrixThread.get(); } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategyTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategyTest.java index c36de2c43..8290d7227 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategyTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategyTest.java @@ -51,12 +51,11 @@ import static org.assertj.core.api.BDDAssertions.then; public class SleuthHystrixConcurrencyStrategyTest { ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); @Before @After @@ -67,27 +66,31 @@ public class SleuthHystrixConcurrencyStrategyTest { @Test public void should_not_override_existing_custom_strategies() { - HystrixPlugins.getInstance().registerCommandExecutionHook(new MyHystrixCommandExecutionHook()); + HystrixPlugins.getInstance() + .registerCommandExecutionHook(new MyHystrixCommandExecutionHook()); HystrixPlugins.getInstance().registerEventNotifier(new MyHystrixEventNotifier()); - HystrixPlugins.getInstance().registerMetricsPublisher(new MyHystrixMetricsPublisher()); - HystrixPlugins.getInstance().registerPropertiesStrategy(new MyHystrixPropertiesStrategy()); + HystrixPlugins.getInstance() + .registerMetricsPublisher(new MyHystrixMetricsPublisher()); + HystrixPlugins.getInstance() + .registerPropertiesStrategy(new MyHystrixPropertiesStrategy()); new SleuthHystrixConcurrencyStrategy(this.tracing, new DefaultSpanNamer()); - then(HystrixPlugins - .getInstance().getCommandExecutionHook()).isExactlyInstanceOf(MyHystrixCommandExecutionHook.class); - then(HystrixPlugins.getInstance() - .getEventNotifier()).isExactlyInstanceOf(MyHystrixEventNotifier.class); - then(HystrixPlugins.getInstance() - .getMetricsPublisher()).isExactlyInstanceOf(MyHystrixMetricsPublisher.class); - then(HystrixPlugins.getInstance() - .getPropertiesStrategy()).isExactlyInstanceOf(MyHystrixPropertiesStrategy.class); + then(HystrixPlugins.getInstance().getCommandExecutionHook()) + .isExactlyInstanceOf(MyHystrixCommandExecutionHook.class); + then(HystrixPlugins.getInstance().getEventNotifier()) + .isExactlyInstanceOf(MyHystrixEventNotifier.class); + then(HystrixPlugins.getInstance().getMetricsPublisher()) + .isExactlyInstanceOf(MyHystrixMetricsPublisher.class); + then(HystrixPlugins.getInstance().getPropertiesStrategy()) + .isExactlyInstanceOf(MyHystrixPropertiesStrategy.class); } @Test public void should_wrap_delegates_callable_in_trace_callable_when_delegate_is_present() throws Exception { - HystrixPlugins.getInstance().registerConcurrencyStrategy(new MyHystrixConcurrencyStrategy()); + HystrixPlugins.getInstance() + .registerConcurrencyStrategy(new MyHystrixConcurrencyStrategy()); SleuthHystrixConcurrencyStrategy strategy = new SleuthHystrixConcurrencyStrategy( this.tracing, new DefaultSpanNamer()); @@ -109,8 +112,7 @@ public class SleuthHystrixConcurrencyStrategyTest { } @Test - public void should_add_trace_keys_when_span_is_created() - throws Exception { + public void should_add_trace_keys_when_span_is_created() throws Exception { SleuthHystrixConcurrencyStrategy strategy = new SleuthHystrixConcurrencyStrategy( this.tracing, new DefaultSpanNamer()); Callable callable = strategy.wrapCallable(() -> "hello"); @@ -124,40 +126,60 @@ public class SleuthHystrixConcurrencyStrategyTest { @Test public void should_delegate_work_to_custom_hystrix_concurrency_strategy() throws Exception { - HystrixConcurrencyStrategy strategy = Mockito.mock(HystrixConcurrencyStrategy.class); + HystrixConcurrencyStrategy strategy = Mockito + .mock(HystrixConcurrencyStrategy.class); HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy); SleuthHystrixConcurrencyStrategy sleuthStrategy = new SleuthHystrixConcurrencyStrategy( this.tracing, new DefaultSpanNamer()); sleuthStrategy.wrapCallable(() -> "foo"); - sleuthStrategy.getThreadPool(HystrixThreadPoolKey.Factory.asKey(""), Mockito.mock( - HystrixThreadPoolProperties.class)); + sleuthStrategy.getThreadPool(HystrixThreadPoolKey.Factory.asKey(""), + Mockito.mock(HystrixThreadPoolProperties.class)); sleuthStrategy.getThreadPool(HystrixThreadPoolKey.Factory.asKey(""), Mockito.mock(HystrixProperty.class), Mockito.mock(HystrixProperty.class), - Mockito.mock(HystrixProperty.class), TimeUnit.DAYS, Mockito.mock( - BlockingQueue.class)); + Mockito.mock(HystrixProperty.class), TimeUnit.DAYS, + Mockito.mock(BlockingQueue.class)); sleuthStrategy.getBlockingQueue(10); - sleuthStrategy.getRequestVariable(Mockito.mock( - HystrixLifecycleForwardingRequestVariable.class)); + sleuthStrategy.getRequestVariable( + Mockito.mock(HystrixLifecycleForwardingRequestVariable.class)); BDDMockito.then(strategy).should().wrapCallable((Callable) BDDMockito.any()); - BDDMockito.then(strategy).should().getThreadPool(BDDMockito.any(), BDDMockito.any()); - BDDMockito.then(strategy).should().getThreadPool(BDDMockito.any(), BDDMockito.any(), - BDDMockito.any(), BDDMockito.any(), BDDMockito.any(), BDDMockito.any()); - BDDMockito.then(strategy).should().getThreadPool(BDDMockito.any(), BDDMockito.any(), - BDDMockito.any(), BDDMockito.any(), BDDMockito.any(), BDDMockito.any()); + BDDMockito.then(strategy).should().getThreadPool(BDDMockito.any(), + BDDMockito.any()); + BDDMockito.then(strategy).should().getThreadPool(BDDMockito.any(), + BDDMockito.any(), BDDMockito.any(), BDDMockito.any(), BDDMockito.any(), + BDDMockito.any()); + BDDMockito.then(strategy).should().getThreadPool(BDDMockito.any(), + BDDMockito.any(), BDDMockito.any(), BDDMockito.any(), BDDMockito.any(), + BDDMockito.any()); BDDMockito.then(strategy).should().getBlockingQueue(10); BDDMockito.then(strategy).should().getRequestVariable(BDDMockito.any()); } - static class MyHystrixCommandExecutionHook extends HystrixCommandExecutionHook {} + static class MyHystrixCommandExecutionHook extends HystrixCommandExecutionHook { + + } + @SuppressWarnings("unchecked") static class MyHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy { - @Override public Callable wrapCallable(Callable callable) { + + @Override + public Callable wrapCallable(Callable callable) { return () -> (T) "executed_custom_callable"; } + } - static class MyHystrixEventNotifier extends HystrixEventNotifier {} - static class MyHystrixMetricsPublisher extends HystrixMetricsPublisher {} - static class MyHystrixPropertiesStrategy extends HystrixPropertiesStrategy {} + + static class MyHystrixEventNotifier extends HystrixEventNotifier { + + } + + static class MyHystrixMetricsPublisher extends HystrixMetricsPublisher { + + } + + static class MyHystrixPropertiesStrategy extends HystrixPropertiesStrategy { + + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommandTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommandTests.java index f5db3d927..c114c4b9d 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommandTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/TraceCommandTests.java @@ -42,13 +42,12 @@ import static org.assertj.core.api.BDDAssertions.then; public class TraceCommandTests { ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .sampler(Sampler.ALWAYS_SAMPLE) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).sampler(Sampler.ALWAYS_SAMPLE).build(); + Tracer tracer = this.tracing.tracer(); @Before @@ -65,18 +64,19 @@ public class TraceCommandTests { Span secondSpanFromHystrix = whenCommandIsExecuted(traceReturningCommand()); then(secondSpanFromHystrix.context().traceId()).as("second trace id") - .isNotEqualTo(firstSpanFromHystrix.context().traceId()).as("first trace id"); + .isNotEqualTo(firstSpanFromHystrix.context().traceId()) + .as("first trace id"); } + @Test public void should_create_a_local_span_with_proper_tags_when_hystrix_command_gets_executed() throws Exception { whenCommandIsExecuted(traceReturningCommand()); then(this.reporter.getSpans()).hasSize(1); - then(this.reporter.getSpans().get(0).tags()) - .containsEntry("commandKey", "traceCommandKey"); - then(this.reporter.getSpans().get(0).duration()) - .isGreaterThan(0L); + then(this.reporter.getSpans().get(0).tags()).containsEntry("commandKey", + "traceCommandKey"); + then(this.reporter.getSpans().get(0).duration()).isGreaterThan(0L); } @Test @@ -86,15 +86,15 @@ public class TraceCommandTests { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { TraceCommand command = traceReturningCommand(); whenCommandIsExecuted(command); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(2); then(spans.get(0).traceId()).isEqualTo(span.context().traceIdString()); - then(spans.get(0).tags()) - .containsEntry("commandKey", "traceCommandKey") + then(spans.get(0).tags()).containsEntry("commandKey", "traceCommandKey") .containsEntry("commandGroup", "group") .containsEntry("threadPoolKey", "group"); } @@ -140,11 +140,13 @@ public class TraceCommandTests { throw new FooException(); } - @Override public Span doGetFallback() { + @Override + public Span doGetFallback() { return tracer.currentSpan(); } - @Override protected String getFallbackMethodName() { + @Override + protected String getFallbackMethodName() { return super.getFallbackMethodName() + "_foobar"; } }; @@ -156,24 +158,22 @@ public class TraceCommandTests { List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).traceId()).isEqualTo(span.context().traceIdString()); - then(spans.get(0).tags()) - .containsEntry("commandKey", "command") + then(spans.get(0).tags()).containsEntry("commandKey", "command") .containsEntry("commandGroup", "group") .containsEntry("threadPoolKey", "group") .containsEntry("fallbackMethodName", "getFallback_foobar"); } - private String someLogic(){ + private String someLogic() { return "some logic"; } private TraceCommand traceReturningCommand() { - return new TraceCommand(this.tracer, - withGroupKey(asKey("group")) - .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties - .Setter().withCoreSize(1).withMaxQueueSize(1)) - .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() - .withExecutionTimeoutEnabled(false)) + return new TraceCommand(this.tracer, withGroupKey(asKey("group")) + .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter() + .withCoreSize(1).withMaxQueueSize(1)) + .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() + .withExecutionTimeoutEnabled(false)) .andCommandKey(HystrixCommandKey.Factory.asKey("traceCommandKey"))) { @Override public Span doRun() throws Exception { @@ -189,6 +189,9 @@ public class TraceCommandTests { private Span givenACommandWasExecuted(TraceCommand command) { return whenCommandIsExecuted(command); } + } -class FooException extends RuntimeException {} \ No newline at end of file +class FooException extends RuntimeException { + +} \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/ITTracingChannelInterceptor.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/ITTracingChannelInterceptor.java index 1be92c518..5b27a1fd0 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/ITTracingChannelInterceptor.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/ITTracingChannelInterceptor.java @@ -50,29 +50,38 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; /** - * Ported from org.springframework.cloud.sleuth.instrument.messaging.TraceChannelInterceptorTest to + * Ported from + * org.springframework.cloud.sleuth.instrument.messaging.TraceChannelInterceptorTest to * allow sleuth to decommission its implementation. */ -@SpringBootTest(classes = ITTracingChannelInterceptor.App.class, - webEnvironment = SpringBootTest.WebEnvironment.NONE) +@SpringBootTest(classes = ITTracingChannelInterceptor.App.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) @RunWith(SpringRunner.class) @DirtiesContext public class ITTracingChannelInterceptor implements MessageHandler { - @Autowired @Qualifier("directChannel") DirectChannel directChannel; + @Autowired + @Qualifier("directChannel") + DirectChannel directChannel; - @Autowired @Qualifier("executorChannel") ExecutorChannel executorChannel; + @Autowired + @Qualifier("executorChannel") + ExecutorChannel executorChannel; - @Autowired Tracer tracer; + @Autowired + Tracer tracer; - @Autowired List spans; + @Autowired + List spans; - @Autowired MessagingTemplate messagingTemplate; + @Autowired + MessagingTemplate messagingTemplate; Message message; + Span currentSpan; - @Override public void handleMessage(Message msg) { + @Override + public void handleMessage(Message msg) { message = msg; currentSpan = tracer.currentSpan(); if (message.getHeaders().containsKey("THROW_EXCEPTION")) { @@ -80,75 +89,83 @@ public class ITTracingChannelInterceptor implements MessageHandler { } } - @Before public void init() { + @Before + public void init() { directChannel.subscribe(this); executorChannel.subscribe(this); } - @After public void close() { + @After + public void close() { directChannel.unsubscribe(this); executorChannel.unsubscribe(this); } // formerly known as TraceChannelInterceptorTest.executableSpanCreation - @Test public void propagatesNoopSpan() { - directChannel.send(MessageBuilder.withPayload("hi").setHeader("X-B3-Sampled", "0") - .build()); + @Test + public void propagatesNoopSpan() { + directChannel.send( + MessageBuilder.withPayload("hi").setHeader("X-B3-Sampled", "0").build()); assertThat(message.getHeaders()).containsEntry("X-B3-Sampled", "0"); assertThat(currentSpan.isNoop()).isTrue(); } - @Test public void messageHeadersStillMutableForStomp() { - directChannel.send(MessageBuilder.withPayload("hi").setHeader("stompCommand", "DISCONNECT") - .build()); + @Test + public void messageHeadersStillMutableForStomp() { + directChannel.send(MessageBuilder.withPayload("hi") + .setHeader("stompCommand", "DISCONNECT").build()); assertThat( MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class)) - .isNotNull(); + .isNotNull(); message = null; - directChannel.send(MessageBuilder.withPayload("hi").setHeader("simpMessageType", "sth") - .build()); + directChannel.send(MessageBuilder.withPayload("hi") + .setHeader("simpMessageType", "sth").build()); assertThat( MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class)) - .isNotNull(); + .isNotNull(); } - @Test public void messageHeadersImmutableForNonStomp() { - directChannel.send(MessageBuilder.withPayload("hi").setHeader("foo", "bar") - .build()); + @Test + public void messageHeadersImmutableForNonStomp() { + directChannel + .send(MessageBuilder.withPayload("hi").setHeader("foo", "bar").build()); assertThat( MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class)) - .isNull(); + .isNull(); } @Configuration @EnableAutoConfiguration static class App { - @Bean List spans() { + @Bean + List spans() { return new ArrayList<>(); } - @Bean Tracing tracing() { + @Bean + Tracing tracing() { return Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) + .addScopeDecorator(StrictScopeDecorator.create()).build()) .spanReporter(spans()::add).build(); } - @Bean Tracer tracer() { + @Bean + Tracer tracer() { return tracing().tracer(); } ExecutorService service = Executors.newSingleThreadExecutor(); - @Bean ExecutorChannel executorChannel() { + @Bean + ExecutorChannel executorChannel() { return new ExecutorChannel(this.service); } @@ -157,12 +174,16 @@ public class ITTracingChannelInterceptor implements MessageHandler { this.service.shutdown(); } - @Bean DirectChannel directChannel() { + @Bean + DirectChannel directChannel() { return new DirectChannel(); } - @Bean public MessagingTemplate messagingTemplate() { + @Bean + public MessagingTemplate messagingTemplate() { return new MessagingTemplate(directChannel()); } + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/JmsTracingConfigurationTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/JmsTracingConfigurationTest.java index 894d1ad9f..ca4efe450 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/JmsTracingConfigurationTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/JmsTracingConfigurationTest.java @@ -67,19 +67,21 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Adrian Cole */ public class JmsTracingConfigurationTest { + final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations - .of(AnnotationJmsListenerConfiguration.class, - XAConfiguration.class, - SimpleJmsListenerConfiguration.class, + .withConfiguration( + AutoConfigurations.of(AnnotationJmsListenerConfiguration.class, + XAConfiguration.class, SimpleJmsListenerConfiguration.class, JcaJmsListenerConfiguration.class, JmsTestTracingConfiguration.class)); - @Test public void tracesConnectionFactory() { + @Test + public void tracesConnectionFactory() { contextRunner.run(JmsTracingConfigurationTest::checkConnection); } - @Test public void tracesXAConnectionFactories() { + @Test + public void tracesXAConnectionFactories() { contextRunner.withUserConfiguration(XAConfiguration.class).run(ctx -> { checkConnection(ctx); checkXAConnection(ctx); @@ -88,34 +90,40 @@ public class JmsTracingConfigurationTest { @AutoConfigureBefore(ActiveMQAutoConfiguration.class) static class XAConfiguration { - @Bean XAConnectionFactoryWrapper xaConnectionFactoryWrapper() { + + @Bean + XAConnectionFactoryWrapper xaConnectionFactoryWrapper() { return connectionFactory -> (ConnectionFactory) connectionFactory; } + } - @Test public void tracesListener_jmsMessageListener() { + @Test + public void tracesListener_jmsMessageListener() { contextRunner.withUserConfiguration(SimpleJmsListenerConfiguration.class) .run(ctx -> { ctx.getBean(JmsTemplate.class).convertAndSend("myQueue", "foo"); Callable takeSpan = ctx.getBean("takeSpan", Callable.class); - List trace = Arrays - .asList(takeSpan.call(), takeSpan.call(), takeSpan.call()); + List trace = Arrays.asList(takeSpan.call(), takeSpan.call(), + takeSpan.call()); assertThat(trace).allSatisfy(s -> assertThat(s.traceId()) .isEqualTo(trace.get(0).traceId())); - assertThat(trace).extracting(Span::name) - .containsExactly("send", "receive", "on-message"); + assertThat(trace).extracting(Span::name).containsExactly("send", + "receive", "on-message"); }); } @Configuration @EnableJms static class SimpleJmsListenerConfiguration implements JmsListenerConfigurer { - @Autowired CurrentTraceContext current; - @Override public void configureJmsListeners( - JmsListenerEndpointRegistrar registrar) { + @Autowired + CurrentTraceContext current; + + @Override + public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) { SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint(); endpoint.setId("myCustomEndpointId"); endpoint.setDestination("myQueue"); @@ -123,62 +131,74 @@ public class JmsTracingConfigurationTest { registrar.registerEndpoint(endpoint); } - @Bean MessageListener simpleMessageListener(CurrentTraceContext current) { + @Bean + MessageListener simpleMessageListener(CurrentTraceContext current) { return message -> { // Didn't restart the trace assertThat(current.get()).extracting(TraceContext::parentIdAsLong) .isNotEqualTo(0L); }; } + } - @Test public void tracesListener_annotationMessageListener() { + @Test + public void tracesListener_annotationMessageListener() { contextRunner.withUserConfiguration(AnnotationJmsListenerConfiguration.class) .run(ctx -> { ctx.getBean(JmsTemplate.class).convertAndSend("myQueue", "foo"); Callable takeSpan = ctx.getBean("takeSpan", Callable.class); - List trace = Arrays - .asList(takeSpan.call(), takeSpan.call(), takeSpan.call()); + List trace = Arrays.asList(takeSpan.call(), takeSpan.call(), + takeSpan.call()); assertThat(trace).allSatisfy(s -> assertThat(s.traceId()) .isEqualTo(trace.get(0).traceId())); - assertThat(trace).extracting(Span::name) - .containsExactly("send", "receive", "on-message"); + assertThat(trace).extracting(Span::name).containsExactly("send", + "receive", "on-message"); }); } @Configuration @EnableJms static class AnnotationJmsListenerConfiguration { - @Autowired CurrentTraceContext current; - @JmsListener(destination = "myQueue") public void onMessage() { + @Autowired + CurrentTraceContext current; + + @JmsListener(destination = "myQueue") + public void onMessage() { assertThat(current.get()).extracting(TraceContext::parentIdAsLong) .isNotEqualTo(0L); } + } - @Test public void tracesListener_jcaMessageListener() { + @Test + public void tracesListener_jcaMessageListener() { contextRunner.withUserConfiguration(JcaJmsListenerConfiguration.class) .run(ctx -> { ctx.getBean(JmsTemplate.class).convertAndSend("myQueue", "foo"); Callable takeSpan = ctx.getBean("takeSpan", Callable.class); - List trace = Arrays - .asList(takeSpan.call(), takeSpan.call(), takeSpan.call()); + List trace = Arrays.asList(takeSpan.call(), takeSpan.call(), + takeSpan.call()); assertThat(trace).allSatisfy(s -> assertThat(s.traceId()) .isEqualTo(trace.get(0).traceId())); - assertThat(trace).extracting(Span::name) - .containsExactly("send", "receive", "on-message"); + assertThat(trace).extracting(Span::name).containsExactly("send", + "receive", "on-message"); }); } - @Configuration static class JcaJmsListenerConfiguration { - @Autowired CurrentTraceContext current; + @Configuration + static class JcaJmsListenerConfiguration { - @Bean ResourceAdapterFactoryBean resourceAdapter() { + @Autowired + CurrentTraceContext current; + + @Bean + ResourceAdapterFactoryBean resourceAdapter() { ResourceAdapterFactoryBean resourceAdapter = new ResourceAdapterFactoryBean(); ActiveMQResourceAdapter real = new ActiveMQResourceAdapter(); real.setServerUrl("vm://localhost?broker.persistent=false"); @@ -187,7 +207,8 @@ public class JmsTracingConfigurationTest { return resourceAdapter; } - @Bean MessageListener simpleMessageListener(CurrentTraceContext current) { + @Bean + MessageListener simpleMessageListener(CurrentTraceContext current) { return message -> { // Didn't restart the trace assertThat(current.get()).extracting(TraceContext::parentIdAsLong) @@ -195,7 +216,8 @@ public class JmsTracingConfigurationTest { }; } - @Bean JmsMessageEndpointManager endpointManager(ResourceAdapter resourceAdapter, + @Bean + JmsMessageEndpointManager endpointManager(ResourceAdapter resourceAdapter, MessageListener simpleMessageListener) { JmsMessageEndpointManager endpointManager = new JmsMessageEndpointManager(); endpointManager.setResourceAdapter(resourceAdapter); @@ -209,6 +231,7 @@ public class JmsTracingConfigurationTest { endpointManager.setMessageListener(simpleMessageListener); return endpointManager; } + } static void checkConnection(AssertableApplicationContext ctx) throws JMSException { @@ -238,24 +261,28 @@ public class JmsTracingConfigurationTest { con.close(); } } + } @Configuration @EnableAutoConfiguration class JmsTestTracingConfiguration { + static final String CONTEXT_LEAK = "context.leak"; /** - * When testing servers or asynchronous clients, spans are reported on a worker thread. In order - * to read them on the main thread, we use a concurrent queue. As some implementations report - * after a response is sent, we use a blocking queue to prevent race conditions in tests. + * When testing servers or asynchronous clients, spans are reported on a worker + * thread. In order to read them on the main thread, we use a concurrent queue. As + * some implementations report after a response is sent, we use a blocking queue to + * prevent race conditions in tests. */ BlockingQueue spans = new LinkedBlockingQueue<>(); /** * Call this to block until a span was reported */ - @Bean Callable takeSpan() { + @Bean + Callable takeSpan() { return () -> { Span result = spans.poll(3, TimeUnit.SECONDS); assertThat(result).withFailMessage("Span was not reported").isNotNull(); @@ -265,13 +292,15 @@ class JmsTestTracingConfiguration { }; } - @Bean Tracing tracing(CurrentTraceContext currentTraceContext) { + @Bean + Tracing tracing(CurrentTraceContext currentTraceContext) { return Tracing.newBuilder().spanReporter(s -> { // make sure the context was cleared prior to finish.. no leaks! TraceContext current = currentTraceContext.get(); boolean contextLeak = false; if (current != null) { - // add annotation in addition to throwing, in case we are off the main thread + // add annotation in addition to throwing, in case we are off the main + // thread if (HexCodec.toLowerHex(current.spanId()).equals(s.id())) { s = s.toBuilder().addAnnotation(s.timestampAsLong(), CONTEXT_LEAK) .build(); @@ -286,4 +315,5 @@ class JmsTestTracingConfiguration { } }).currentTraceContext(currentTraceContext).build(); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagationTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagationTest.java index 939552afc..ff1fd88e8 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagationTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagationTest.java @@ -27,27 +27,31 @@ import static org.junit.Assert.*; public class MessageHeaderPropagationTest extends PropagationSetterTest { + MessageHeaderAccessor carrier = new MessageHeaderAccessor(); - @Override public Propagation.KeyFactory keyFactory() { + @Override + public Propagation.KeyFactory keyFactory() { return Propagation.KeyFactory.STRING; } - @Override protected MessageHeaderAccessor carrier() { + @Override + protected MessageHeaderAccessor carrier() { return carrier; } - @Override protected Propagation.Setter setter() { + @Override + protected Propagation.Setter setter() { return MessageHeaderPropagation.INSTANCE; } - @Override protected Iterable read(MessageHeaderAccessor carrier, String key) { + @Override + protected Iterable read(MessageHeaderAccessor carrier, String key) { Object result = carrier.getHeader(key); - return result != null ? - Collections.singleton(result.toString()) : - Collections.emptyList(); + return result != null ? Collections.singleton(result.toString()) + : Collections.emptyList(); } - + @Test public void testGetByteArrayValue() { MessageHeaderAccessor carrier = carrier(); @@ -56,7 +60,7 @@ public class MessageHeaderPropagationTest String value = MessageHeaderPropagation.INSTANCE.get(carrier, "X-B3-TraceId"); assertEquals("48485a3953bb6124000000", value); } - + @Test public void testGetStringValue() { MessageHeaderAccessor carrier = carrier(); @@ -65,7 +69,7 @@ public class MessageHeaderPropagationTest String value = MessageHeaderPropagation.INSTANCE.get(carrier, "X-B3-TraceId"); assertEquals("48485a3953bb61240000000", value); } - + @Test public void testGetNullValue() { MessageHeaderAccessor carrier = carrier(); @@ -79,8 +83,7 @@ public class MessageHeaderPropagationTest public void testSkipWrongValueTypeForGet() { MessageHeaderAccessor carrier = carrier(); carrier.setHeader(NativeMessageHeaderAccessor.NATIVE_HEADERS, - "{spanTraceId=[123], spanId=[456], spanSampled=[0]}" - ); + "{spanTraceId=[123], spanId=[456], spanSampled=[0]}"); MessageHeaderPropagation.INSTANCE.get(carrier, "X-B3-SpanId"); } @@ -88,17 +91,17 @@ public class MessageHeaderPropagationTest public void testSkipWrongValueTypeForRemoval() { MessageHeaderAccessor carrier = carrier(); carrier.setHeader(NativeMessageHeaderAccessor.NATIVE_HEADERS, - "{spanTraceId=[123], spanId=[456], spanSampled=[0]}" - ); - MessageHeaderPropagation.removeAnyTraceHeaders(carrier, Collections.singletonList("X-B3-SpanId")); + "{spanTraceId=[123], spanId=[456], spanSampled=[0]}"); + MessageHeaderPropagation.removeAnyTraceHeaders(carrier, + Collections.singletonList("X-B3-SpanId")); } @Test public void testSkipWrongValueTypeForPut() { MessageHeaderAccessor carrier = carrier(); carrier.setHeader(NativeMessageHeaderAccessor.NATIVE_HEADERS, - "{spanTraceId=[123], spanId=[456], spanSampled=[0]}" - ); + "{spanTraceId=[123], spanId=[456], spanSampled=[0]}"); MessageHeaderPropagation.INSTANCE.put(carrier, "X-B3-SpanId", "1234"); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagation_NativeTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagation_NativeTest.java index 9f211a4d1..540edc77e 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagation_NativeTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/MessageHeaderPropagation_NativeTest.java @@ -25,22 +25,28 @@ import org.springframework.messaging.support.NativeMessageHeaderAccessor; */ public class MessageHeaderPropagation_NativeTest extends PropagationSetterTest { + NativeMessageHeaderAccessor carrier = new NativeMessageHeaderAccessor() { }; - @Override public Propagation.KeyFactory keyFactory() { + @Override + public Propagation.KeyFactory keyFactory() { return Propagation.KeyFactory.STRING; } - @Override protected MessageHeaderAccessor carrier() { + @Override + protected MessageHeaderAccessor carrier() { return carrier; } - @Override protected Propagation.Setter setter() { + @Override + protected Propagation.Setter setter() { return MessageHeaderPropagation.INSTANCE; } - @Override protected Iterable read(MessageHeaderAccessor carrier, String key) { + @Override + protected Iterable read(MessageHeaderAccessor carrier, String key) { return ((NativeMessageHeaderAccessor) carrier).getNativeHeader(key); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/PropagationSetterTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/PropagationSetterTest.java index d8a83bc8f..2531e0b75 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/PropagationSetterTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/PropagationSetterTest.java @@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Taken from Brave */ public abstract class PropagationSetterTest { + protected abstract Propagation.KeyFactory keyFactory(); protected abstract C carrier(); @@ -33,14 +34,16 @@ public abstract class PropagationSetterTest { protected abstract Iterable read(C carrier, K key); - @Test public void set() throws Exception { + @Test + public void set() throws Exception { K key = keyFactory().create("X-B3-TraceId"); setter().put(carrier(), key, "48485a3953bb6124"); assertThat(read(carrier(), key)).containsExactly("48485a3953bb6124"); } - @Test public void set128() throws Exception { + @Test + public void set128() throws Exception { K key = keyFactory().create("X-B3-TraceId"); setter().put(carrier(), key, "463ac35c9f6413ad48485a3953bb6124"); @@ -48,7 +51,8 @@ public abstract class PropagationSetterTest { .containsExactly("463ac35c9f6413ad48485a3953bb6124"); } - @Test public void setTwoKeys() throws Exception { + @Test + public void setTwoKeys() throws Exception { K key1 = keyFactory().create("X-B3-TraceId"); K key2 = keyFactory().create("X-B3-SpanId"); setter().put(carrier(), key1, "463ac35c9f6413ad48485a3953bb6124"); @@ -59,12 +63,13 @@ public abstract class PropagationSetterTest { assertThat(read(carrier(), key2)).containsExactly("48485a3953bb6124"); } - @Test public void reset() throws Exception { + @Test + public void reset() throws Exception { K key = keyFactory().create("X-B3-TraceId"); setter().put(carrier(), key, "48485a3953bb6124"); setter().put(carrier(), key, "463ac35c9f6413ad"); assertThat(read(carrier(), key)).containsExactly("463ac35c9f6413ad"); } -} +} diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceContextPropagationChannelInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceContextPropagationChannelInterceptorTests.java index a703d1dd6..515bb0f34 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceContextPropagationChannelInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceContextPropagationChannelInterceptorTests.java @@ -50,37 +50,45 @@ import static org.junit.Assert.assertNotNull; @DirtiesContext public class TraceContextPropagationChannelInterceptorTests { - @Autowired @Qualifier("channel") private PollableChannel channel; + @Autowired + @Qualifier("channel") + private PollableChannel channel; - @Autowired private Tracing tracing; - @Autowired private ArrayListSpanReporter reporter; + @Autowired + private Tracing tracing; - @After public void close() { + @Autowired + private ArrayListSpanReporter reporter; + + @After + public void close() { this.reporter.clear(); } - @Test public void testSpanPropagation() { + @Test + public void testSpanPropagation() { Span span = this.tracing.tracer().nextSpan().name("http:testSendMessage").start(); String expectedSpanId = SpanUtil.idToHex(span.context().spanId()); try (Tracer.SpanInScope ws = this.tracing.tracer().withSpanInScope(span)) { this.channel.send(MessageBuilder.withPayload("hi").build()); - } finally { + } + finally { span.finish(); } Message message = this.channel.receive(0); assertNotNull("message was null", message); - String spanId = - message.getHeaders().get(TraceMessageHeaders.SPAN_ID_NAME, String.class); + String spanId = message.getHeaders().get(TraceMessageHeaders.SPAN_ID_NAME, + String.class); assertNotEquals("spanId was equal to parent's id", expectedSpanId, spanId); - String traceId = message.getHeaders() - .get(TraceMessageHeaders.TRACE_ID_NAME, String.class); + String traceId = message.getHeaders().get(TraceMessageHeaders.TRACE_ID_NAME, + String.class); assertNotNull("traceId was null", traceId); - String parentId = message.getHeaders() - .get(TraceMessageHeaders.PARENT_ID_NAME, String.class); + String parentId = message.getHeaders().get(TraceMessageHeaders.PARENT_ID_NAME, + String.class); assertEquals("parentId was not equal to parent's id", this.reporter.getSpans().get(0).id(), parentId); @@ -90,16 +98,21 @@ public class TraceContextPropagationChannelInterceptorTests { @EnableAutoConfiguration static class App { - @Bean public QueueChannel channel() { + @Bean + public QueueChannel channel() { return new QueueChannel(); } - @Bean Sampler testSampler() { + @Bean + Sampler testSampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfigurationTests.java index 6aba4842d..66cfae806 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfigurationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfigurationTests.java @@ -48,17 +48,29 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = TraceMessagingAutoConfigurationTests.Config.class, - webEnvironment = SpringBootTest.WebEnvironment.NONE) +@SpringBootTest(classes = TraceMessagingAutoConfigurationTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) public class TraceMessagingAutoConfigurationTests { - @Autowired RabbitTemplate rabbitTemplate; - @Autowired ArrayListSpanReporter reporter; - @Autowired TestSleuthRabbitBeanPostProcessor postProcessor; - @Autowired TestSleuthJmsBeanPostProcessor jmsBeanPostProcessor; - @Autowired MySleuthKafkaAspect mySleuthKafkaAspect; - @Autowired ProducerFactory producerFactory; - @Autowired ConsumerFactory consumerFactory; + @Autowired + RabbitTemplate rabbitTemplate; + + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + TestSleuthRabbitBeanPostProcessor postProcessor; + + @Autowired + TestSleuthJmsBeanPostProcessor jmsBeanPostProcessor; + + @Autowired + MySleuthKafkaAspect mySleuthKafkaAspect; + + @Autowired + ProducerFactory producerFactory; + + @Autowired + ConsumerFactory consumerFactory; @Test public void should_wrap_rabbit_template() { @@ -86,21 +98,31 @@ public class TraceMessagingAutoConfigurationTests { @Configuration @EnableAutoConfiguration protected static class Config { - @Bean Sampler sampler() { + + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } - @Bean SleuthRabbitBeanPostProcessor sleuthRabbitBeanPostProcessor(BeanFactory beanFactory) { + @Bean + SleuthRabbitBeanPostProcessor sleuthRabbitBeanPostProcessor( + BeanFactory beanFactory) { return new TestSleuthRabbitBeanPostProcessor(beanFactory); } - @Bean SleuthKafkaAspect sleuthKafkaAspect(KafkaTracing kafkaTracing, Tracer tracer) { + + @Bean + SleuthKafkaAspect sleuthKafkaAspect(KafkaTracing kafkaTracing, Tracer tracer) { return new MySleuthKafkaAspect(kafkaTracing, tracer); } - @Bean TestSleuthJmsBeanPostProcessor sleuthJmsBeanPostProcessor(BeanFactory beanFactory) { + + @Bean + TestSleuthJmsBeanPostProcessor sleuthJmsBeanPostProcessor( + BeanFactory beanFactory) { return new TestSleuthJmsBeanPostProcessor(beanFactory); } @@ -108,7 +130,9 @@ public class TraceMessagingAutoConfigurationTests { public void onMessage(ConsumerRecord message) { System.err.println(message); } + } + } class TestSleuthRabbitBeanPostProcessor extends SleuthRabbitBeanPostProcessor { @@ -119,39 +143,45 @@ class TestSleuthRabbitBeanPostProcessor extends SleuthRabbitBeanPostProcessor { super(beanFactory); } - @Override SpringRabbitTracing rabbitTracing() { + @Override + SpringRabbitTracing rabbitTracing() { this.rabbitTracingCalled = true; return super.rabbitTracing(); } + } class MySleuthKafkaAspect extends SleuthKafkaAspect { boolean producerWrapped; + boolean consumerWrapped; + boolean adapterWrapped; MySleuthKafkaAspect(KafkaTracing kafkaTracing, Tracer tracer) { super(kafkaTracing, tracer); } - @Override public Object wrapProducerFactory(ProceedingJoinPoint pjp) - throws Throwable { + @Override + public Object wrapProducerFactory(ProceedingJoinPoint pjp) throws Throwable { this.producerWrapped = true; return Mockito.mock(Producer.class); } - @Override public Object wrapConsumerFactory(ProceedingJoinPoint pjp) - throws Throwable { + @Override + public Object wrapConsumerFactory(ProceedingJoinPoint pjp) throws Throwable { this.consumerWrapped = true; return Mockito.mock(Consumer.class); } - @Override public Object wrapListenerContainerCreation(ProceedingJoinPoint pjp) + @Override + public Object wrapListenerContainerCreation(ProceedingJoinPoint pjp) throws Throwable { this.adapterWrapped = true; return Mockito.mock(MessageListenerContainer.class); } + } class TestSleuthJmsBeanPostProcessor extends TracingConnectionFactoryBeanPostProcessor { @@ -162,9 +192,11 @@ class TestSleuthJmsBeanPostProcessor extends TracingConnectionFactoryBeanPostPro super(beanFactory); } - @Override public Object postProcessAfterInitialization(Object bean, String beanName) + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { this.tracingCalled = true; return super.postProcessAfterInitialization(bean, beanName); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptorAutowireTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptorAutowireTest.java index 1de345a7b..4e75aaae6 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptorAutowireTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptorAutowireTest.java @@ -26,13 +26,18 @@ import org.springframework.messaging.support.ChannelInterceptor; public class TracingChannelInterceptorAutowireTest { - @Configuration static class TracingConfiguration { - @Bean Tracing tracing() { + @Configuration + static class TracingConfiguration { + + @Bean + Tracing tracing() { return Tracing.newBuilder().build(); } + } - @Test public void autowiredWithBeanConfig() { + @Test + public void autowiredWithBeanConfig() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(TracingConfiguration.class); ctx.register(TracingChannelInterceptor.class); @@ -41,7 +46,9 @@ public class TracingChannelInterceptorAutowireTest { ctx.getBean(ChannelInterceptor.class); } - @After public void close() { + @After + public void close() { Tracing.current().close(); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptorTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptorTest.java index fb2bc9cd6..220982019 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptorTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TracingChannelInterceptorTest.java @@ -49,16 +49,18 @@ import static org.springframework.messaging.support.NativeMessageHeaderAccessor. public class TracingChannelInterceptorTest { List spans = new ArrayList<>(); + ChannelInterceptor interceptor = TracingChannelInterceptor.create(Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(spans::add) - .build()); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(spans::add).build()); QueueChannel channel = new QueueChannel(); + DirectChannel directChannel = new DirectChannel(); + Message message; + MessageHandler handler = new MessageHandler() { @Override public void handleMessage(Message msg) throws MessagingException { @@ -66,39 +68,41 @@ public class TracingChannelInterceptorTest { } }; - @Test public void pollingReceive_emptyQueue() { + @Test + public void pollingReceive_emptyQueue() { channel.addInterceptor(consumerSideOnly(interceptor)); assertThat(channel.receive(0)).isNull(); assertThat(spans).hasSize(0); } - @Test public void injectsProducerSpan() { + @Test + public void injectsProducerSpan() { channel.addInterceptor(producerSideOnly(interceptor)); channel.send(MessageBuilder.withPayload("foo").build()); - assertThat(channel.receive().getHeaders()) - .containsKeys("X-B3-TraceId", "X-B3-SpanId", "X-B3-Sampled", - "nativeHeaders"); + assertThat(channel.receive().getHeaders()).containsKeys("X-B3-TraceId", + "X-B3-SpanId", "X-B3-Sampled", "nativeHeaders"); assertThat(spans).hasSize(1).flatExtracting(Span::kind) .containsExactly(Span.Kind.PRODUCER); } - @Test public void injectsProducerAndConsumerSpan() { + @Test + public void injectsProducerAndConsumerSpan() { directChannel.addInterceptor(interceptor); directChannel.subscribe(this.handler); directChannel.send(MessageBuilder.withPayload("foo").build()); assertThat(message).isNotNull(); - assertThat(message.getHeaders()) - .containsKeys("X-B3-TraceId", "X-B3-SpanId", "X-B3-Sampled", - "nativeHeaders"); - assertThat(spans).flatExtracting(Span::kind) - .contains(Span.Kind.CONSUMER, Span.Kind.PRODUCER); + assertThat(message.getHeaders()).containsKeys("X-B3-TraceId", "X-B3-SpanId", + "X-B3-Sampled", "nativeHeaders"); + assertThat(spans).flatExtracting(Span::kind).contains(Span.Kind.CONSUMER, + Span.Kind.PRODUCER); } - @Test public void injectsProducerSpan_nativeHeaders() { + @Test + public void injectsProducerSpan_nativeHeaders() { channel.addInterceptor(producerSideOnly(interceptor)); channel.send(MessageBuilder.withPayload("foo").build()); @@ -109,10 +113,12 @@ public class TracingChannelInterceptorTest { } /** - * If the producer is acting on an un-processed message (ex via a polling consumer), it should - * look at trace headers when there is no span in scope, and use that as the parent context. + * If the producer is acting on an un-processed message (ex via a polling consumer), + * it should look at trace headers when there is no span in scope, and use that as the + * parent context. */ - @Test public void producerConsidersOldSpanIds() { + @Test + public void producerConsidersOldSpanIds() { channel.addInterceptor(producerSideOnly(interceptor)); channel.send(MessageBuilder.withPayload("foo") @@ -120,11 +126,12 @@ public class TracingChannelInterceptorTest { .setHeader("X-B3-ParentSpanId", "000000000000000a") .setHeader("X-B3-SpanId", "000000000000000b").build()); - assertThat(channel.receive().getHeaders()) - .containsEntry("X-B3-ParentSpanId", "000000000000000b"); + assertThat(channel.receive().getHeaders()).containsEntry("X-B3-ParentSpanId", + "000000000000000b"); } - @Test public void producerConsidersOldSpanIds_nativeHeaders() { + @Test + public void producerConsidersOldSpanIds_nativeHeaders() { channel.addInterceptor(producerSideOnly(interceptor)); NativeMessageHeaderAccessor accessor = new NativeMessageHeaderAccessor() { @@ -134,9 +141,8 @@ public class TracingChannelInterceptorTest { accessor.setNativeHeader("X-B3-ParentSpanId", "000000000000000a"); accessor.setNativeHeader("X-B3-SpanId", "000000000000000b"); - channel.send( - MessageBuilder.withPayload("foo").copyHeaders(accessor.toMessageHeaders()) - .build()); + channel.send(MessageBuilder.withPayload("foo") + .copyHeaders(accessor.toMessageHeaders()).build()); assertThat((Map) channel.receive().getHeaders().get(NATIVE_HEADERS)) .containsEntry("X-B3-ParentSpanId", @@ -144,21 +150,23 @@ public class TracingChannelInterceptorTest { } /** - * We have to inject headers on a polling receive as any future processor will come later + * We have to inject headers on a polling receive as any future processor will come + * later */ - @Test public void pollingReceive_injectsConsumerSpan() { + @Test + public void pollingReceive_injectsConsumerSpan() { channel.addInterceptor(consumerSideOnly(interceptor)); channel.send(MessageBuilder.withPayload("foo").build()); - assertThat(channel.receive().getHeaders()) - .containsKeys("X-B3-TraceId", "X-B3-SpanId", "X-B3-Sampled", - "nativeHeaders"); + assertThat(channel.receive().getHeaders()).containsKeys("X-B3-TraceId", + "X-B3-SpanId", "X-B3-Sampled", "nativeHeaders"); assertThat(spans).hasSize(1).flatExtracting(Span::kind) .containsExactly(Span.Kind.CONSUMER); } - @Test public void pollingReceive_injectsConsumerSpan_nativeHeaders() { + @Test + public void pollingReceive_injectsConsumerSpan_nativeHeaders() { channel.addInterceptor(consumerSideOnly(interceptor)); channel.send(MessageBuilder.withPayload("foo").build()); @@ -168,7 +176,8 @@ public class TracingChannelInterceptorTest { "spanTraceId", "spanId", "spanSampled"); } - @Test public void subscriber_startsAndStopsConsumerAndProcessingSpan() { + @Test + public void subscriber_startsAndStopsConsumerAndProcessingSpan() { ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(); channel.addInterceptor(executorSideOnly(interceptor)); List> messages = new ArrayList<>(); @@ -176,18 +185,19 @@ public class TracingChannelInterceptorTest { channel.send(MessageBuilder.withPayload("foo").build()); - assertThat(messages.get(0).getHeaders()) - .doesNotContainKeys("X-B3-TraceId", "X-B3-SpanId", "X-B3-Sampled", - "nativeHeaders"); - assertThat(spans).flatExtracting(Span::kind) - .containsExactly(Span.Kind.CONSUMER, null); + assertThat(messages.get(0).getHeaders()).doesNotContainKeys("X-B3-TraceId", + "X-B3-SpanId", "X-B3-Sampled", "nativeHeaders"); + assertThat(spans).flatExtracting(Span::kind).containsExactly(Span.Kind.CONSUMER, + null); } /** - * The subscriber consumes a message then synchronously processes it. Since we only inject trace - * IDs on unprocessed messages, we remove IDs to prevent accidental re-use of the same span. + * The subscriber consumes a message then synchronously processes it. Since we only + * inject trace IDs on unprocessed messages, we remove IDs to prevent accidental + * re-use of the same span. */ - @Test public void subscriber_removesTraceIdsFromMessage() { + @Test + public void subscriber_removesTraceIdsFromMessage() { ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(); channel.addInterceptor(interceptor); List> messages = new ArrayList<>(); @@ -195,11 +205,12 @@ public class TracingChannelInterceptorTest { channel.send(MessageBuilder.withPayload("foo").build()); - assertThat(messages.get(0).getHeaders()) - .doesNotContainKeys("X-B3-TraceId", "X-B3-SpanId", "X-B3-Sampled"); + assertThat(messages.get(0).getHeaders()).doesNotContainKeys("X-B3-TraceId", + "X-B3-SpanId", "X-B3-Sampled"); } - @Test public void subscriber_removesTraceIdsFromMessage_nativeHeaders() { + @Test + public void subscriber_removesTraceIdsFromMessage_nativeHeaders() { ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(); channel.addInterceptor(interceptor); List> messages = new ArrayList<>(); @@ -211,7 +222,8 @@ public class TracingChannelInterceptorTest { .doesNotContainKeys("X-B3-TraceId", "X-B3-SpanId", "X-B3-Sampled"); } - @Test public void integrated_sendAndPoll() { + @Test + public void integrated_sendAndPoll() { channel.addInterceptor(interceptor); channel.send(MessageBuilder.withPayload("foo").build()); @@ -221,7 +233,8 @@ public class TracingChannelInterceptorTest { .containsExactlyInAnyOrder(Span.Kind.CONSUMER, Span.Kind.PRODUCER); } - @Test public void integrated_sendAndSubscriber() { + @Test + public void integrated_sendAndSubscriber() { ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(); channel.addInterceptor(interceptor); List> messages = new ArrayList<>(); @@ -229,8 +242,8 @@ public class TracingChannelInterceptorTest { channel.send(MessageBuilder.withPayload("foo").build()); - assertThat(spans).flatExtracting(Span::kind) - .containsExactly(Span.Kind.CONSUMER, null, Span.Kind.PRODUCER); + assertThat(spans).flatExtracting(Span::kind).containsExactly(Span.Kind.CONSUMER, + null, Span.Kind.PRODUCER); } @Test @@ -241,26 +254,32 @@ public class TracingChannelInterceptorTest { Map errorChannelHeaders = new HashMap<>(); errorChannelHeaders.put(MessageHeaders.REPLY_CHANNEL, errorsReplyChannel); errorChannelHeaders.put(MessageHeaders.ERROR_CHANNEL, errorsReplyChannel); - this.channel.send(new ErrorMessage( - new MessagingException(MessageBuilder.withPayload("hi") - .setHeader(TraceMessageHeaders.TRACE_ID_NAME, "000000000000000a") - .setHeader(TraceMessageHeaders.SPAN_ID_NAME, "000000000000000a") - .setReplyChannel(deadReplyChannel) - .setErrorChannel(deadReplyChannel) - .build()), - errorChannelHeaders)); + this.channel + .send(new ErrorMessage( + new MessagingException(MessageBuilder.withPayload("hi") + .setHeader(TraceMessageHeaders.TRACE_ID_NAME, + "000000000000000a") + .setHeader(TraceMessageHeaders.SPAN_ID_NAME, + "000000000000000a") + .setReplyChannel(deadReplyChannel) + .setErrorChannel(deadReplyChannel).build()), + errorChannelHeaders)); this.message = this.channel.receive(); assertThat(this.message).isNotNull(); - String spanId = this.message.getHeaders().get(TraceMessageHeaders.SPAN_ID_NAME, String.class); + String spanId = this.message.getHeaders().get(TraceMessageHeaders.SPAN_ID_NAME, + String.class); assertThat(spanId).isNotNull(); - String traceId = this.message.getHeaders().get(TraceMessageHeaders.TRACE_ID_NAME, String.class); + String traceId = this.message.getHeaders().get(TraceMessageHeaders.TRACE_ID_NAME, + String.class); assertThat(traceId).isEqualTo("000000000000000a"); assertThat(spanId).isNotEqualTo("000000000000000a"); assertThat(this.spans).hasSize(2); - assertThat(this.message.getHeaders().getReplyChannel()).isSameAs(errorsReplyChannel); - assertThat(this.message.getHeaders().getErrorChannel()).isSameAs(errorsReplyChannel); + assertThat(this.message.getHeaders().getReplyChannel()) + .isSameAs(errorsReplyChannel); + assertThat(this.message.getHeaders().getErrorChannel()) + .isSameAs(errorsReplyChannel); } ChannelInterceptor producerSideOnly(ChannelInterceptor delegate) { @@ -296,25 +315,29 @@ public class TracingChannelInterceptorTest { ExecutorChannelInterceptor executorSideOnly(ChannelInterceptor delegate) { class ExecutorSideOnly extends ChannelInterceptorAdapter implements ExecutorChannelInterceptor { + @Override public Message beforeHandle(Message message, MessageChannel channel, MessageHandler handler) { - return ((ExecutorChannelInterceptor) delegate) - .beforeHandle(message, channel, handler); + return ((ExecutorChannelInterceptor) delegate).beforeHandle(message, + channel, handler); } @Override public void afterMessageHandled(Message message, MessageChannel channel, MessageHandler handler, Exception ex) { - ((ExecutorChannelInterceptor) delegate) - .afterMessageHandled(message, channel, handler, ex); + ((ExecutorChannelInterceptor) delegate).afterMessageHandled(message, + channel, handler, ex); } + } return new ExecutorSideOnly(); } - @After public void close() { + @After + public void close() { assertThat(Tracing.current().currentTraceContext().get()).isNull(); Tracing.current().close(); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/CustomExecutorConfig.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/CustomExecutorConfig.java index 2961b43d8..3f9188a87 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/CustomExecutorConfig.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/CustomExecutorConfig.java @@ -1,46 +1,49 @@ -/* - * Copyright 2013-2018 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.messaging.issues.issue_943; - -import java.util.concurrent.Executor; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.AsyncConfigurerSupport; -import org.springframework.scheduling.annotation.EnableAsync; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; - -@EnableAsync -@Configuration -public class CustomExecutorConfig extends AsyncConfigurerSupport { - - @Autowired BeanFactory beanFactory; - - @Override public Executor getAsyncExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - // CUSTOMIZE HERE - executor.setCorePoolSize(7); - executor.setMaxPoolSize(42); - executor.setQueueCapacity(11); - executor.setThreadNamePrefix("MyExecutor-"); - // DON'T FORGET TO INITIALIZE - executor.initialize(); - return new LazyTraceExecutor(this.beanFactory, executor); - } +/* + * Copyright 2013-2018 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.messaging.issues.issue_943; + +import java.util.concurrent.Executor; + +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurerSupport; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +@EnableAsync +@Configuration +public class CustomExecutorConfig extends AsyncConfigurerSupport { + + @Autowired + BeanFactory beanFactory; + + @Override + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + // CUSTOMIZE HERE + executor.setCorePoolSize(7); + executor.setMaxPoolSize(42); + executor.setQueueCapacity(11); + executor.setThreadNamePrefix("MyExecutor-"); + // DON'T FORGET TO INITIALIZE + executor.initialize(); + return new LazyTraceExecutor(this.beanFactory, executor); + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloSpringIntegration.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloSpringIntegration.java index cc4a7384b..4e0c65cd8 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloSpringIntegration.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloSpringIntegration.java @@ -30,7 +30,8 @@ import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.web.client.RestTemplate; @SpringBootApplication -@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class}) +@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, + HibernateJpaAutoConfiguration.class }) @ImportResource("classpath:beans/applicationContext.xml") @EnableIntegration @EnableAsync @@ -40,15 +41,19 @@ public class HelloSpringIntegration { SpringApplication.run(HelloSpringIntegration.class, args); } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean RestTemplate restTemplate() { + @Bean + RestTemplate restTemplate() { return new RestTemplate(); } - @Bean ArrayListSpanReporter accumulator() { + @Bean + ArrayListSpanReporter accumulator() { return new ArrayListSpanReporter(); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloWorldImpl.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloWorldImpl.java index bacdfb7a7..3b25d1c20 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloWorldImpl.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloWorldImpl.java @@ -1,52 +1,51 @@ -/* - * Copyright 2013-2018 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.messaging.issues.issue_943; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class HelloWorldImpl { - - private static final Logger LOG = LoggerFactory.getLogger(HelloWorldImpl.class); - - public String invokeProcessor(String message) throws InterruptedException { - LOG.info(" input message "+message); - Thread.currentThread().sleep(500); - LOG.info(" After the Sleep "+message); - String responseMessage = message + " Persist into DB "; - return responseMessage; - } - - - public List aggregate(List requestMessage) { - LOG.info(Thread.currentThread().getName()); - LOG.info(" requestMessage aggregate "+requestMessage); - return requestMessage; - } - - - public List splitMessage(String[] splitRequest){ - LOG.info(" Inside splitMessage " +splitRequest); - List splitGBSResponse = new ArrayList(); - splitGBSResponse = Arrays.asList(splitRequest); - return splitGBSResponse; - } -} +/* + * Copyright 2013-2018 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.messaging.issues.issue_943; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HelloWorldImpl { + + private static final Logger LOG = LoggerFactory.getLogger(HelloWorldImpl.class); + + public String invokeProcessor(String message) throws InterruptedException { + LOG.info(" input message " + message); + Thread.currentThread().sleep(500); + LOG.info(" After the Sleep " + message); + String responseMessage = message + " Persist into DB "; + return responseMessage; + } + + public List aggregate(List requestMessage) { + LOG.info(Thread.currentThread().getName()); + LOG.info(" requestMessage aggregate " + requestMessage); + return requestMessage; + } + + public List splitMessage(String[] splitRequest) { + LOG.info(" Inside splitMessage " + splitRequest); + List splitGBSResponse = new ArrayList(); + splitGBSResponse = Arrays.asList(splitRequest); + return splitGBSResponse; + } + +} diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloWorldRestController.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloWorldRestController.java index bff4c3568..10896c242 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloWorldRestController.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/HelloWorldRestController.java @@ -1,68 +1,70 @@ -/* - * Copyright 2013-2018 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.messaging.issues.issue_943; - -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.messaging.PollableChannel; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; - -@RestController -public class HelloWorldRestController { - - private static final Logger LOG = LoggerFactory.getLogger(HelloWorldRestController.class); - - @Autowired - private ApplicationContext applicationContext; - - @RequestMapping(path = "getHelloWorldMessage", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) - public ResponseEntity getHelloWorld() throws Exception { - - LOG.info("Inside getHelloWorldMessage"); - - String[] requestMessage = new String[3]; - requestMessage[0] = "Hellow World Message 1"; - requestMessage[1] = "Hellow World Message 2"; - requestMessage[2] = "Hellow World Message 3"; - - PollableChannel outputChannel = (PollableChannel) applicationContext.getBean("messagingOutputChannel"); - - MessagingGateway messagingGateway = (MessagingGateway) applicationContext - .getBean("messagingGateway"); - - messagingGateway.processMessage(requestMessage); - - GenericMessage reply = (GenericMessage) outputChannel.receive(); - - List body = (List) reply.getPayload(); - - LOG.info(" Response Message " + body); - - return new ResponseEntity(body.toString(), HttpStatus.OK); - } - -} +/* + * Copyright 2013-2018 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.messaging.issues.issue_943; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.messaging.PollableChannel; +import org.springframework.messaging.support.GenericMessage; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloWorldRestController { + + private static final Logger LOG = LoggerFactory + .getLogger(HelloWorldRestController.class); + + @Autowired + private ApplicationContext applicationContext; + + @RequestMapping(path = "getHelloWorldMessage", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity getHelloWorld() throws Exception { + + LOG.info("Inside getHelloWorldMessage"); + + String[] requestMessage = new String[3]; + requestMessage[0] = "Hellow World Message 1"; + requestMessage[1] = "Hellow World Message 2"; + requestMessage[2] = "Hellow World Message 3"; + + PollableChannel outputChannel = (PollableChannel) applicationContext + .getBean("messagingOutputChannel"); + + MessagingGateway messagingGateway = (MessagingGateway) applicationContext + .getBean("messagingGateway"); + + messagingGateway.processMessage(requestMessage); + + GenericMessage reply = (GenericMessage) outputChannel.receive(); + + List body = (List) reply.getPayload(); + + LOG.info(" Response Message " + body); + + return new ResponseEntity(body.toString(), HttpStatus.OK); + } + +} diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/Issue943Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/Issue943Tests.java index f89631cd4..79b1cccda 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/Issue943Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/Issue943Tests.java @@ -35,36 +35,42 @@ public class Issue943Tests { @Test public void should_pass_tracing_context_via_spring_integration() { - try (ConfigurableApplicationContext applicationContext = SpringApplication - .run(HelloSpringIntegration.class, "--spring.jmx.enabled=false", "--server.port=0")) { + try (ConfigurableApplicationContext applicationContext = SpringApplication.run( + HelloSpringIntegration.class, "--spring.jmx.enabled=false", + "--server.port=0")) { // given Tracer tracer = applicationContext.getBean(Tracer.class); Span newSpan = tracer.nextSpan().name("foo").start(); String object; try (Tracer.SpanInScope ws = tracer.withSpanInScope(newSpan)) { - RestTemplate restTemplate = applicationContext.getBean(RestTemplate.class); + RestTemplate restTemplate = applicationContext + .getBean(RestTemplate.class); // when - object = restTemplate.getForObject( - "http://localhost:" + applicationContext.getEnvironment() - .getProperty("local.server.port") + "/getHelloWorldMessage", - String.class); + object = restTemplate + .getForObject( + "http://localhost:" + + applicationContext.getEnvironment() + .getProperty("local.server.port") + + "/getHelloWorldMessage", + String.class); } // then - ArrayListSpanReporter accumulator = applicationContext.getBean(ArrayListSpanReporter.class); - then(object) - .contains("Hellow World Message 1 Persist into DB") + ArrayListSpanReporter accumulator = applicationContext + .getBean(ArrayListSpanReporter.class); + then(object).contains("Hellow World Message 1 Persist into DB") .contains("Hellow World Message 2 Persist into DB") .contains("Hellow World Message 3 Persist into DB"); - then(accumulator.getSpans().stream() - .filter(span -> span.traceId().equals(newSpan.context().traceIdString())) - .map(span -> span.tags().getOrDefault("channel", span.tags().get("http.path"))) + then(accumulator.getSpans().stream().filter( + span -> span.traceId().equals(newSpan.context().traceIdString())) + .map(span -> span.tags().getOrDefault("channel", + span.tags().get("http.path"))) .collect(Collectors.toList())) - .as("trace context was propagated successfully") - .isNotEmpty() - .contains("splitterOutChannel", "messagingChannel", - "messagingProcessedChannel", "messagingOutputChannel", - "/getHelloWorldMessage"); + .as("trace context was propagated successfully").isNotEmpty() + .contains("splitterOutChannel", "messagingChannel", + "messagingProcessedChannel", "messagingOutputChannel", + "/getHelloWorldMessage"); } } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/MessagingGateway.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/MessagingGateway.java index 3fbceca56..8c39b98d8 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/MessagingGateway.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/issues/issue_943/MessagingGateway.java @@ -1,23 +1,23 @@ -/* - * Copyright 2013-2018 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.messaging.issues.issue_943; - -public interface MessagingGateway { - - void processMessage(String[] messageArray); - -} +/* + * Copyright 2013-2018 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.messaging.issues.issue_943; + +public interface MessagingGateway { + + void processMessage(String[] messageArray); + +} diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/websocket/TraceWebSocketAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/websocket/TraceWebSocketAutoConfigurationTests.java index 95e589e13..317b63362 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/websocket/TraceWebSocketAutoConfigurationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/websocket/TraceWebSocketAutoConfigurationTests.java @@ -44,16 +44,17 @@ public class TraceWebSocketAutoConfigurationTests { @Autowired DelegatingWebSocketMessageBrokerConfiguration delegatingWebSocketMessageBrokerConfiguration; - @Test public void should_register_interceptors_for_all_channels() { + @Test + public void should_register_interceptors_for_all_channels() { then(this.delegatingWebSocketMessageBrokerConfiguration.clientInboundChannel() .getInterceptors()) - .hasAtLeastOneElementOfType(TracingChannelInterceptor.class); + .hasAtLeastOneElementOfType(TracingChannelInterceptor.class); then(this.delegatingWebSocketMessageBrokerConfiguration.clientOutboundChannel() .getInterceptors()) - .hasAtLeastOneElementOfType(TracingChannelInterceptor.class); + .hasAtLeastOneElementOfType(TracingChannelInterceptor.class); then(this.delegatingWebSocketMessageBrokerConfiguration.brokerChannel() .getInterceptors()) - .hasAtLeastOneElementOfType(TracingChannelInterceptor.class); + .hasAtLeastOneElementOfType(TracingChannelInterceptor.class); } @EnableAutoConfiguration @@ -61,17 +62,22 @@ public class TraceWebSocketAutoConfigurationTests { @EnableWebSocketMessageBroker public static class Config extends AbstractWebSocketMessageBrokerConfigurer { - @Override public void configureMessageBroker(MessageBrokerRegistry config) { + @Override + public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } - @Override public void registerStompEndpoints(StompEndpointRegistry registry) { + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/hello").withSockJS(); } - @Bean Sampler testSampler() { + @Bean + Sampler testSampler() { return Sampler.ALWAYS_SAMPLE; } + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/multiple/DemoApplication.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/multiple/DemoApplication.java index d2efb5323..6c9bd2b74 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/multiple/DemoApplication.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/multiple/DemoApplication.java @@ -46,33 +46,40 @@ public class DemoApplication { private static final Log log = LogFactory.getLog(DemoApplication.class); Span httpSpan; + Span splitterSpan; + Span aggregatorSpan; + Span serviceActivatorSpan; - @Autowired Sender sender; - @Autowired Tracer tracer; + @Autowired + Sender sender; + + @Autowired + Tracer tracer; @RequestMapping("/greeting") - public Greeting greeting(@RequestParam(defaultValue="Hello World!") String message, @RequestHeader HttpHeaders headers) { + public Greeting greeting(@RequestParam(defaultValue = "Hello World!") String message, + @RequestHeader HttpHeaders headers) { this.sender.send(message); this.httpSpan = this.tracer.currentSpan(); return new Greeting(message); } - @Splitter(inputChannel="greetings", outputChannel="words") + @Splitter(inputChannel = "greetings", outputChannel = "words") public List words(String greeting) { this.splitterSpan = this.tracer.currentSpan(); return Arrays.asList(StringUtils.delimitedListToStringArray(greeting, " ")); } - @Aggregator(inputChannel="words", outputChannel="counts") + @Aggregator(inputChannel = "words", outputChannel = "counts") public int count(List greeting) { this.aggregatorSpan = this.tracer.currentSpan(); return greeting.size(); } - @ServiceActivator(inputChannel="counts") + @ServiceActivator(inputChannel = "counts") public void report(int count) { this.serviceActivatorSpan = this.tracer.currentSpan(); log.info("Count: " + count); @@ -95,18 +102,22 @@ public class DemoApplication { } public List allSpans() { - return Arrays.asList(this.httpSpan, this.splitterSpan, this.aggregatorSpan, this.serviceActivatorSpan); + return Arrays.asList(this.httpSpan, this.splitterSpan, this.aggregatorSpan, + this.serviceActivatorSpan); } } @MessagingGateway(name = "greeter") interface Sender { + @Gateway(requestChannel = "greetings") void send(String message); + } class Greeting { + private String message; Greeting() { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/multiple/MultipleHopsIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/multiple/MultipleHopsIntegrationTests.java index e8c9aedbd..8cf42cafd 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/multiple/MultipleHopsIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/multiple/MultipleHopsIntegrationTests.java @@ -52,20 +52,26 @@ import static org.assertj.core.api.BDDAssertions.then; import static org.awaitility.Awaitility.await; @RunWith(SpringJUnit4ClassRunner.class) -@TestPropertySource(properties = { - "spring.application.name=multiplehopsintegrationtests", - "spring.sleuth.http.legacy.enabled=true" -}) -@SpringBootTest(classes = MultipleHopsIntegrationTests.Config.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { "spring.application.name=multiplehopsintegrationtests", + "spring.sleuth.http.legacy.enabled=true" }) +@SpringBootTest(classes = MultipleHopsIntegrationTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles("baggage") public class MultipleHopsIntegrationTests { - @Autowired Tracer tracer; - @Autowired ArrayListSpanReporter reporter; - @Autowired RestTemplate restTemplate; - @Autowired Config config; - @Autowired DemoApplication application; + @Autowired + Tracer tracer; + + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + RestTemplate restTemplate; + + @Autowired + Config config; + + @Autowired + DemoApplication application; @Before public void setup() { @@ -74,52 +80,52 @@ public class MultipleHopsIntegrationTests { @Test public void should_prepare_spans_for_export() throws Exception { - this.restTemplate.getForObject("http://localhost:" + this.config.port + "/greeting", String.class); + this.restTemplate.getForObject( + "http://localhost:" + this.config.port + "/greeting", String.class); await().atMost(5, SECONDS).untilAsserted(() -> { then(this.reporter.getSpans()).hasSize(14); }); - then(this.reporter.getSpans().stream().map(zipkin2.Span::name) - .collect(toList())).containsAll(asList("http:/greeting", "send")); + then(this.reporter.getSpans().stream().map(zipkin2.Span::name).collect(toList())) + .containsAll(asList("http:/greeting", "send")); then(this.reporter.getSpans().stream().map(zipkin2.Span::kind) // no server kind due to test constraints - .collect(toList())).containsAll(asList(zipkin2.Span.Kind.CONSUMER, - zipkin2.Span.Kind.PRODUCER, zipkin2.Span.Kind.SERVER)); - then(this.reporter.getSpans().stream() - .map(span -> span.tags().get("channel")) - .filter(Objects::nonNull) - .distinct() .collect(toList())) - .hasSize(3) - .containsAll(asList("words", "counts", "greetings")); + .containsAll(asList(zipkin2.Span.Kind.CONSUMER, + zipkin2.Span.Kind.PRODUCER, zipkin2.Span.Kind.SERVER)); + then(this.reporter.getSpans().stream().map(span -> span.tags().get("channel")) + .filter(Objects::nonNull).distinct().collect(toList())).hasSize(3) + .containsAll(asList("words", "counts", "greetings")); } // issue #237 - baggage @Test // Notes: - // * path-prefix header propagation can't reliably support mixed case, due to http/2 downcasing - // * Since not all tokenizers are case insensitive, mixed case can break correlation - // * Brave's ExtraFieldPropagation downcases due to the above - // * This code should probably test the side-effect on http headers - // * the assumption all correlation fields (baggage) are saved to a span is an interesting one - // * should all correlation fields (baggage) be added to the MDC context? + // * path-prefix header propagation can't reliably support mixed case, due to http/2 + // downcasing + // * Since not all tokenizers are case insensitive, mixed case can break correlation + // * Brave's ExtraFieldPropagation downcases due to the above + // * This code should probably test the side-effect on http headers + // * the assumption all correlation fields (baggage) are saved to a span is an + // interesting one + // * should all correlation fields (baggage) be added to the MDC context? // * Until below, a configuration item of a correlation field whitelist is needed - // * https://github.com/openzipkin/brave/pull/577 - // * probably needed anyway as an empty whitelist is a nice way to disable the feature + // * https://github.com/openzipkin/brave/pull/577 + // * probably needed anyway as an empty whitelist is a nice way to disable the feature public void should_propagate_the_baggage() throws Exception { - //tag::baggage[] + // tag::baggage[] Span initialSpan = this.tracer.nextSpan().name("span").start(); ExtraFieldPropagation.set(initialSpan.context(), "foo", "bar"); - ExtraFieldPropagation.set(initialSpan.context(),"UPPER_CASE", "someValue"); - //end::baggage[] + ExtraFieldPropagation.set(initialSpan.context(), "UPPER_CASE", "someValue"); + // end::baggage[] try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initialSpan)) { - //tag::baggage_tag[] + // tag::baggage_tag[] initialSpan.tag("foo", ExtraFieldPropagation.get(initialSpan.context(), "foo")); initialSpan.tag("UPPER_CASE", ExtraFieldPropagation.get(initialSpan.context(), "UPPER_CASE")); - //end::baggage_tag[] + // end::baggage_tag[] HttpHeaders headers = new HttpHeaders(); headers.put("baggage-baz", Collections.singletonList("baz")); @@ -127,7 +133,8 @@ public class MultipleHopsIntegrationTests { RequestEntity requestEntity = new RequestEntity(headers, HttpMethod.GET, URI.create("http://localhost:" + this.config.port + "/greeting")); this.restTemplate.exchange(requestEntity, String.class); - } finally { + } + finally { initialSpan.finish(); } await().atMost(5, SECONDS).untilAsserted(() -> { @@ -138,23 +145,17 @@ public class MultipleHopsIntegrationTests { .allMatch(span -> "bar".equals(baggage(span, "foo"))); then(this.application.allSpans()).as("All have UPPER_CASE") .allMatch(span -> "someValue".equals(baggage(span, "UPPER_CASE"))); - then(this.application.allSpans() - .stream() + then(this.application.allSpans().stream() .filter(span -> "baz".equals(baggage(span, "baz"))) - .collect(Collectors.toList())) - .as("Someone has baz") - .isNotEmpty(); - then(this.reporter.getSpans() - .stream() - .filter(span -> span.tags().containsKey("foo") && span.tags().containsKey("UPPER_CASE")) - .collect(Collectors.toList())) - .as("Someone has foo and UPPER_CASE tags") - .isNotEmpty(); - then(this.application.allSpans() - .stream() + .collect(Collectors.toList())).as("Someone has baz").isNotEmpty(); + then(this.reporter.getSpans().stream() + .filter(span -> span.tags().containsKey("foo") + && span.tags().containsKey("UPPER_CASE")) + .collect(Collectors.toList())).as("Someone has foo and UPPER_CASE tags") + .isNotEmpty(); + then(this.application.allSpans().stream() .filter(span -> "value".equals(baggage(span, "bizarreCASE"))) - .collect(Collectors.toList())) - .isNotEmpty(); + .collect(Collectors.toList())).isNotEmpty(); } private String baggage(Span span, String name) { @@ -163,8 +164,9 @@ public class MultipleHopsIntegrationTests { @Configuration @SpringBootApplication(exclude = JmxAutoConfiguration.class) - public static class Config implements - ApplicationListener { + public static class Config + implements ApplicationListener { + int port; @Override @@ -177,13 +179,16 @@ public class MultipleHopsIntegrationTests { return new RestTemplate(); } - @Bean ArrayListSpanReporter arrayListSpanAccumulator() { + @Bean + ArrayListSpanReporter arrayListSpanAccumulator() { return new ArrayListSpanReporter(); } - @Bean Sampler defaultTraceSampler() { + @Bean + Sampler defaultTraceSampler() { return Sampler.ALWAYS_SAMPLE; } } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/opentracing/BraveTracerTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/opentracing/BraveTracerTest.java index acb68ba77..756c2905e 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/opentracing/BraveTracerTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/opentracing/BraveTracerTest.java @@ -47,272 +47,278 @@ import static org.assertj.core.data.MapEntry.entry; import static org.junit.Assert.assertEquals; /** - * This shows how one might make an OpenTracing adapter for Brave, and how to navigate in and out of - * the core concepts. + * This shows how one might make an OpenTracing adapter for Brave, and how to navigate in + * and out of the core concepts. * - * Adopted from: https://github.com/openzipkin-contrib/brave-opentracing/tree/master/src/test/java/brave/opentracing + * Adopted from: + * https://github.com/openzipkin-contrib/brave-opentracing/tree/master/src/test/java/brave/opentracing */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, -properties = "spring.sleuth.baggage-keys=country-code,user-id") +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = "spring.sleuth.baggage-keys=country-code,user-id") public class BraveTracerTest { - @Autowired ArrayListSpanReporter spans; - @Autowired Tracing brave; - @Autowired BraveTracer opentracing; + @Autowired + ArrayListSpanReporter spans; - @Test public void startWithOpenTracingAndFinishWithBrave() { - io.opentracing.Span openTracingSpan = opentracing.buildSpan("encode") - .withTag("lc", "codec") - .withStartTimestamp(1L) - .start(); + @Autowired + Tracing brave; - Span braveSpan = ((BraveSpan) openTracingSpan).unwrap(); + @Autowired + BraveTracer opentracing; - braveSpan.annotate(2L, "pump fake"); - braveSpan.finish(3L); + @Test + public void startWithOpenTracingAndFinishWithBrave() { + io.opentracing.Span openTracingSpan = opentracing.buildSpan("encode") + .withTag("lc", "codec").withStartTimestamp(1L).start(); - checkSpanReportedToZipkin(); - } + Span braveSpan = ((BraveSpan) openTracingSpan).unwrap(); - @Test public void extractTraceContext() throws Exception { - Map map = new LinkedHashMap<>(); - map.put("X-B3-TraceId", "0000000000000001"); - map.put("X-B3-SpanId", "0000000000000002"); - map.put("X-B3-Sampled", "1"); + braveSpan.annotate(2L, "pump fake"); + braveSpan.finish(3L); - BraveSpanContext openTracingContext = - (BraveSpanContext) opentracing.extract(Format.Builtin.HTTP_HEADERS, - new TextMapExtractAdapter(map)); + checkSpanReportedToZipkin(); + } - assertThat(openTracingContext.unwrap()) - .isEqualTo(TraceContext.newBuilder() - .traceId(1L) - .spanId(2L) - .sampled(true).build()); - } + @Test + public void extractTraceContext() throws Exception { + Map map = new LinkedHashMap<>(); + map.put("X-B3-TraceId", "0000000000000001"); + map.put("X-B3-SpanId", "0000000000000002"); + map.put("X-B3-Sampled", "1"); - @Test public void extractBaggage() throws Exception { - Map map = new LinkedHashMap<>(); - map.put("X-B3-TraceId", "0000000000000001"); - map.put("X-B3-SpanId", "0000000000000002"); - map.put("X-B3-Sampled", "1"); - map.put("baggage-country-code", "FO"); + BraveSpanContext openTracingContext = (BraveSpanContext) opentracing + .extract(Format.Builtin.HTTP_HEADERS, new TextMapExtractAdapter(map)); - BraveSpanContext openTracingContext = opentracing.extract(Format.Builtin.HTTP_HEADERS, - new TextMapExtractAdapter(map)); + assertThat(openTracingContext.unwrap()).isEqualTo( + TraceContext.newBuilder().traceId(1L).spanId(2L).sampled(true).build()); + } - assertThat(openTracingContext.baggageItems()) - .containsExactly(entry("country-code", "FO")); - } + @Test + public void extractBaggage() throws Exception { + Map map = new LinkedHashMap<>(); + map.put("X-B3-TraceId", "0000000000000001"); + map.put("X-B3-SpanId", "0000000000000002"); + map.put("X-B3-Sampled", "1"); + map.put("baggage-country-code", "FO"); - @Test public void extractTraceContextTextMap() throws Exception { - Map map = new LinkedHashMap<>(); - map.put("X-B3-TraceId", "0000000000000001"); - map.put("X-B3-SpanId", "0000000000000002"); - map.put("X-B3-Sampled", "1"); + BraveSpanContext openTracingContext = opentracing + .extract(Format.Builtin.HTTP_HEADERS, new TextMapExtractAdapter(map)); - BraveSpanContext openTracingContext = - (BraveSpanContext) opentracing.extract(Format.Builtin.TEXT_MAP, - new TextMapExtractAdapter(map)); + assertThat(openTracingContext.baggageItems()) + .containsExactly(entry("country-code", "FO")); + } - assertThat(openTracingContext.unwrap()) - .isEqualTo(TraceContext.newBuilder() - .traceId(1L) - .spanId(2L) - .sampled(true).build()); - } + @Test + public void extractTraceContextTextMap() throws Exception { + Map map = new LinkedHashMap<>(); + map.put("X-B3-TraceId", "0000000000000001"); + map.put("X-B3-SpanId", "0000000000000002"); + map.put("X-B3-Sampled", "1"); - @Test public void extractTraceContextCaseInsensitive() throws Exception { - Map map = new LinkedHashMap<>(); - map.put("X-B3-TraceId", "0000000000000001"); - map.put("x-b3-spanid", "0000000000000002"); - map.put("x-b3-SaMpLeD", "1"); - map.put("other", "1"); + BraveSpanContext openTracingContext = (BraveSpanContext) opentracing + .extract(Format.Builtin.TEXT_MAP, new TextMapExtractAdapter(map)); - BraveSpanContext openTracingContext = - (BraveSpanContext) opentracing.extract(Format.Builtin.HTTP_HEADERS, - new TextMapExtractAdapter(map)); + assertThat(openTracingContext.unwrap()).isEqualTo( + TraceContext.newBuilder().traceId(1L).spanId(2L).sampled(true).build()); + } - assertThat(openTracingContext.unwrap()) - .isEqualTo(TraceContext.newBuilder() - .traceId(1L) - .spanId(2L) - .sampled(true).build()); - } + @Test + public void extractTraceContextCaseInsensitive() throws Exception { + Map map = new LinkedHashMap<>(); + map.put("X-B3-TraceId", "0000000000000001"); + map.put("x-b3-spanid", "0000000000000002"); + map.put("x-b3-SaMpLeD", "1"); + map.put("other", "1"); - @Test public void injectTraceContext_baggage() throws Exception { - BraveSpan span = opentracing.buildSpan("foo").start(); - span.setBaggageItem("country-code", "FO"); + BraveSpanContext openTracingContext = (BraveSpanContext) opentracing + .extract(Format.Builtin.HTTP_HEADERS, new TextMapExtractAdapter(map)); - Map map = new LinkedHashMap<>(); - TextMapInjectAdapter carrier = new TextMapInjectAdapter(map); - opentracing.inject(span.context(), Format.Builtin.HTTP_HEADERS, carrier); + assertThat(openTracingContext.unwrap()).isEqualTo( + TraceContext.newBuilder().traceId(1L).spanId(2L).sampled(true).build()); + } - assertThat(map).containsEntry("baggage-country-code", "FO"); - } + @Test + public void injectTraceContext_baggage() throws Exception { + BraveSpan span = opentracing.buildSpan("foo").start(); + span.setBaggageItem("country-code", "FO"); - void checkSpanReportedToZipkin() { - assertThat(spans.getSpans()).first().satisfies(s -> { - assertThat(s.name()).isEqualTo("encode"); - assertThat(s.timestamp()).isEqualTo(1L); - assertThat(s.annotations()) - .containsExactly(Annotation.create(2L, "pump fake")); - assertThat(s.tags()) - .containsExactly(entry("lc", "codec")); - assertThat(s.duration()).isEqualTo(2L); - } - ); - } + Map map = new LinkedHashMap<>(); + TextMapInjectAdapter carrier = new TextMapInjectAdapter(map); + opentracing.inject(span.context(), Format.Builtin.HTTP_HEADERS, carrier); - @Test public void subsequentChildrenNestProperly_OTStyle() { - // this test is semantically identical to subsequentChildrenNestProperly_BraveStyle, but uses - // the OpenTracingAPI instead of the Brave API. + assertThat(map).containsEntry("baggage-country-code", "FO"); + } - Long idOfSpanA; - Long shouldBeIdOfSpanA; - Long idOfSpanB; - Long shouldBeIdOfSpanB; - Long parentIdOfSpanB; - Long parentIdOfSpanC; + void checkSpanReportedToZipkin() { + assertThat(spans.getSpans()).first().satisfies(s -> { + assertThat(s.name()).isEqualTo("encode"); + assertThat(s.timestamp()).isEqualTo(1L); + assertThat(s.annotations()) + .containsExactly(Annotation.create(2L, "pump fake")); + assertThat(s.tags()).containsExactly(entry("lc", "codec")); + assertThat(s.duration()).isEqualTo(2L); + }); + } - try (Scope scopeA = opentracing.buildSpan("spanA").startActive(false)) { - idOfSpanA = getTraceContext(scopeA).spanId(); - try (Scope scopeB = opentracing.buildSpan("spanB").startActive(false)) { - idOfSpanB = getTraceContext(scopeB).spanId(); - parentIdOfSpanB = getTraceContext(scopeB).parentId(); - shouldBeIdOfSpanB = getTraceContext(opentracing.scopeManager().active()).spanId(); - } - shouldBeIdOfSpanA = getTraceContext(opentracing.scopeManager().active()).spanId(); - try (Scope scopeC = opentracing.buildSpan("spanC").startActive(false)) { - parentIdOfSpanC = getTraceContext(scopeC).parentId(); - } - } + @Test + public void subsequentChildrenNestProperly_OTStyle() { + // this test is semantically identical to + // subsequentChildrenNestProperly_BraveStyle, but uses + // the OpenTracingAPI instead of the Brave API. - assertEquals("SpanA should have been active again after closing B", idOfSpanA, - shouldBeIdOfSpanA); - assertEquals("SpanB should have been active prior to its closure", idOfSpanB, - shouldBeIdOfSpanB); - assertEquals("SpanB's parent should be SpanA", idOfSpanA, parentIdOfSpanB); - assertEquals("SpanC's parent should be SpanA", idOfSpanA, parentIdOfSpanC); - } + Long idOfSpanA; + Long shouldBeIdOfSpanA; + Long idOfSpanB; + Long shouldBeIdOfSpanB; + Long parentIdOfSpanB; + Long parentIdOfSpanC; - @Test public void subsequentChildrenNestProperly_BraveStyle() { - // this test is semantically identical to subsequentChildrenNestProperly_OTStyle, but uses - // the Brave API instead of the OpenTracing API. + try (Scope scopeA = opentracing.buildSpan("spanA").startActive(false)) { + idOfSpanA = getTraceContext(scopeA).spanId(); + try (Scope scopeB = opentracing.buildSpan("spanB").startActive(false)) { + idOfSpanB = getTraceContext(scopeB).spanId(); + parentIdOfSpanB = getTraceContext(scopeB).parentId(); + shouldBeIdOfSpanB = getTraceContext(opentracing.scopeManager().active()) + .spanId(); + } + shouldBeIdOfSpanA = getTraceContext(opentracing.scopeManager().active()) + .spanId(); + try (Scope scopeC = opentracing.buildSpan("spanC").startActive(false)) { + parentIdOfSpanC = getTraceContext(scopeC).parentId(); + } + } - Long shouldBeIdOfSpanA; - Long idOfSpanB; - Long shouldBeIdOfSpanB; - Long parentIdOfSpanB; - Long parentIdOfSpanC; + assertEquals("SpanA should have been active again after closing B", idOfSpanA, + shouldBeIdOfSpanA); + assertEquals("SpanB should have been active prior to its closure", idOfSpanB, + shouldBeIdOfSpanB); + assertEquals("SpanB's parent should be SpanA", idOfSpanA, parentIdOfSpanB); + assertEquals("SpanC's parent should be SpanA", idOfSpanA, parentIdOfSpanC); + } - Span spanA = brave.tracer().newTrace().name("spanA").start(); - Long idOfSpanA = spanA.context().spanId(); - try (SpanInScope scopeA = brave.tracer().withSpanInScope(spanA)) { + @Test + public void subsequentChildrenNestProperly_BraveStyle() { + // this test is semantically identical to subsequentChildrenNestProperly_OTStyle, + // but uses + // the Brave API instead of the OpenTracing API. - Span spanB = brave.tracer().newChild(spanA.context()).name("spanB").start(); - idOfSpanB = spanB.context().spanId(); - parentIdOfSpanB = spanB.context().parentId(); - try (SpanInScope scopeB = brave.tracer().withSpanInScope(spanB)) { - shouldBeIdOfSpanB = brave.currentTraceContext().get().spanId(); - } finally { - spanB.finish(); - } + Long shouldBeIdOfSpanA; + Long idOfSpanB; + Long shouldBeIdOfSpanB; + Long parentIdOfSpanB; + Long parentIdOfSpanC; - shouldBeIdOfSpanA = brave.currentTraceContext().get().spanId(); + Span spanA = brave.tracer().newTrace().name("spanA").start(); + Long idOfSpanA = spanA.context().spanId(); + try (SpanInScope scopeA = brave.tracer().withSpanInScope(spanA)) { - Span spanC = brave.tracer().newChild(spanA.context()).name("spanC").start(); - parentIdOfSpanC = spanC.context().parentId(); - try (SpanInScope scopeC = brave.tracer().withSpanInScope(spanC)) { - // nothing to do here - } finally { - spanC.finish(); - } - } finally { - spanA.finish(); - } + Span spanB = brave.tracer().newChild(spanA.context()).name("spanB").start(); + idOfSpanB = spanB.context().spanId(); + parentIdOfSpanB = spanB.context().parentId(); + try (SpanInScope scopeB = brave.tracer().withSpanInScope(spanB)) { + shouldBeIdOfSpanB = brave.currentTraceContext().get().spanId(); + } + finally { + spanB.finish(); + } - assertEquals("SpanA should have been active again after closing B", idOfSpanA, - shouldBeIdOfSpanA); - assertEquals("SpanB should have been active prior to its closure", idOfSpanB, - shouldBeIdOfSpanB); - assertEquals("SpanB's parent should be SpanA", idOfSpanA, parentIdOfSpanB); - assertEquals("SpanC's parent should be SpanA", idOfSpanA, parentIdOfSpanC); - } + shouldBeIdOfSpanA = brave.currentTraceContext().get().spanId(); - @Test public void implicitParentFromSpanManager_startActive() { - try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) { - try (Scope scopeB = opentracing.buildSpan("spanA").startActive(true)) { - assertThat(getTraceContext(scopeB).parentId()) - .isEqualTo(getTraceContext(scopeA).spanId()); - } - } - } + Span spanC = brave.tracer().newChild(spanA.context()).name("spanC").start(); + parentIdOfSpanC = spanC.context().parentId(); + try (SpanInScope scopeC = brave.tracer().withSpanInScope(spanC)) { + // nothing to do here + } + finally { + spanC.finish(); + } + } + finally { + spanA.finish(); + } - @Test public void implicitParentFromSpanManager_start() { - try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) { - BraveSpan span = opentracing.buildSpan("spanB").start(); - assertThat(span.unwrap().context().parentId()) - .isEqualTo(getTraceContext(scopeA).spanId()); - } - } + assertEquals("SpanA should have been active again after closing B", idOfSpanA, + shouldBeIdOfSpanA); + assertEquals("SpanB should have been active prior to its closure", idOfSpanB, + shouldBeIdOfSpanB); + assertEquals("SpanB's parent should be SpanA", idOfSpanA, parentIdOfSpanB); + assertEquals("SpanC's parent should be SpanA", idOfSpanA, parentIdOfSpanC); + } - @Test public void implicitParentFromSpanManager_startActive_ignoreActiveSpan() { - try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) { - try (Scope scopeB = opentracing.buildSpan("spanA") - .ignoreActiveSpan().startActive(true)) { - assertThat(getTraceContext(scopeB).parentId()) - .isNull(); // new trace - } - } - } + @Test + public void implicitParentFromSpanManager_startActive() { + try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) { + try (Scope scopeB = opentracing.buildSpan("spanA").startActive(true)) { + assertThat(getTraceContext(scopeB).parentId()) + .isEqualTo(getTraceContext(scopeA).spanId()); + } + } + } - @Test public void implicitParentFromSpanManager_start_ignoreActiveSpan() { - try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) { - BraveSpan span = opentracing.buildSpan("spanB") - .ignoreActiveSpan().start(); - assertThat(span.unwrap().context().parentId()) - .isNull(); // new trace - } - } + @Test + public void implicitParentFromSpanManager_start() { + try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) { + BraveSpan span = opentracing.buildSpan("spanB").start(); + assertThat(span.unwrap().context().parentId()) + .isEqualTo(getTraceContext(scopeA).spanId()); + } + } - @Test public void ignoresErrorFalseTag_beforeStart() { - opentracing.buildSpan("encode") - .withTag("error", false) - .start().finish(); + @Test + public void implicitParentFromSpanManager_startActive_ignoreActiveSpan() { + try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) { + try (Scope scopeB = opentracing.buildSpan("spanA").ignoreActiveSpan() + .startActive(true)) { + assertThat(getTraceContext(scopeB).parentId()).isNull(); // new trace + } + } + } - assertThat(spans.getSpans().get(0).tags()) - .isEmpty(); - } + @Test + public void implicitParentFromSpanManager_start_ignoreActiveSpan() { + try (Scope scopeA = opentracing.buildSpan("spanA").startActive(true)) { + BraveSpan span = opentracing.buildSpan("spanB").ignoreActiveSpan().start(); + assertThat(span.unwrap().context().parentId()).isNull(); // new trace + } + } - @Test public void ignoresErrorFalseTag_afterStart() { - opentracing.buildSpan("encode") - .start() - .setTag("error", false) - .finish(); + @Test + public void ignoresErrorFalseTag_beforeStart() { + opentracing.buildSpan("encode").withTag("error", false).start().finish(); - assertThat(spans.getSpans().get(0).tags()) - .isEmpty(); - } + assertThat(spans.getSpans().get(0).tags()).isEmpty(); + } - private static TraceContext getTraceContext(Scope scope) { - return ((BraveSpanContext) scope.span().context()).unwrap(); - } + @Test + public void ignoresErrorFalseTag_afterStart() { + opentracing.buildSpan("encode").start().setTag("error", false).finish(); - @Before public void clear() { - this.spans.clear(); - } + assertThat(spans.getSpans().get(0).tags()).isEmpty(); + } - @Configuration - @EnableAutoConfiguration - static class Config { - @Bean Sampler sampler() { - return Sampler.ALWAYS_SAMPLE; - } + private static TraceContext getTraceContext(Scope scope) { + return ((BraveSpanContext) scope.span().context()).unwrap(); + } + + @Before + public void clear() { + this.spans.clear(); + } + + @Configuration + @EnableAutoConfiguration + static class Config { + + @Bean + Sampler sampler() { + return Sampler.ALWAYS_SAMPLE; + } + + @Bean + ArrayListSpanReporter reporter() { + return new ArrayListSpanReporter(); + } + + } - @Bean ArrayListSpanReporter reporter() { - return new ArrayListSpanReporter(); - } - } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/Issue866Configuration.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/Issue866Configuration.java index 78885fc39..845d09720 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/Issue866Configuration.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/Issue866Configuration.java @@ -1,12 +1,12 @@ /* * Copyright 2013-2018 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. @@ -40,14 +40,18 @@ public class Issue866Configuration { return hook; } - public static class TestHook extends HookRegisteringBeanDefinitionRegistryPostProcessor { + public static class TestHook + extends HookRegisteringBeanDefinitionRegistryPostProcessor { + public boolean executed = false; - @Override public void postProcessBeanFactory( - ConfigurableListableBeanFactory beanFactory) throws BeansException { + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) + throws BeansException { super.postProcessBeanFactory(beanFactory); this.executed = true; } - } -} + } + +} diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/ScopePassingSpanSubscriberTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/ScopePassingSpanSubscriberTests.java index eef935906..0e6016733 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/ScopePassingSpanSubscriberTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/ScopePassingSpanSubscriberTests.java @@ -36,16 +36,16 @@ public class ScopePassingSpanSubscriberTests { @Test public void should_propagate_current_context() { - ScopePassingSpanSubscriber subscriber = new ScopePassingSpanSubscriber( - null, Context.of("foo", "bar"), this.tracing); + ScopePassingSpanSubscriber subscriber = new ScopePassingSpanSubscriber(null, + Context.of("foo", "bar"), this.tracing); then((String) subscriber.currentContext().get("foo")).isEqualTo("bar"); } @Test public void should_set_empty_context_when_context_is_null() { - ScopePassingSpanSubscriber subscriber = new ScopePassingSpanSubscriber( - null, null, this.tracing); + ScopePassingSpanSubscriber subscriber = new ScopePassingSpanSubscriber(null, null, + this.tracing); then(subscriber.currentContext().isEmpty()).isTrue(); } @@ -53,12 +53,14 @@ public class ScopePassingSpanSubscriberTests { @Test public void should_put_current_span_to_context() { Span span = this.tracing.tracer().nextSpan(); - try (Tracer.SpanInScope ws = this.tracing.tracer().withSpanInScope(span.start())) { - ScopePassingSpanSubscriber subscriber = new ScopePassingSpanSubscriber( - null, Context.empty(), this.tracing); + try (Tracer.SpanInScope ws = this.tracing.tracer() + .withSpanInScope(span.start())) { + ScopePassingSpanSubscriber subscriber = new ScopePassingSpanSubscriber(null, + Context.empty(), this.tracing); then(subscriber.currentContext().get(Span.class)).isEqualTo(span); } } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriberTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriberTests.java index d51270554..d5758d929 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriberTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/SpanSubscriberTests.java @@ -45,51 +45,28 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringRunner.class) -@SpringBootTest(classes = SpanSubscriberTests.Config.class, - webEnvironment = SpringBootTest.WebEnvironment.NONE) +@SpringBootTest(classes = SpanSubscriberTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) public class SpanSubscriberTests { private static final Log log = LogFactory.getLog(SpanSubscriberTests.class); - @Autowired Tracer tracer; + @Autowired + Tracer tracer; - @Test public void should_pass_tracing_info_when_using_reactor() { + @Test + public void should_pass_tracing_info_when_using_reactor() { Span span = this.tracer.nextSpan().name("foo").start(); final AtomicReference spanInOperation = new AtomicReference<>(); Publisher traced = Flux.just(1, 2, 3); log.info("Hello"); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { - Flux.from(traced) - .map( d -> d + 1) - .map( d -> d + 1) - .map( (d) -> { - spanInOperation.set(this.tracer.currentSpan()); - return d + 1; - }) - .map( d -> d + 1) - .subscribe(System.out::println); - } finally { - span.finish(); - } - - then(this.tracer.currentSpan()).isNull(); - then(spanInOperation.get().context().spanId()) - .isEqualTo(span.context().spanId()); - } - - @Test public void should_support_reactor_fusion_optimization() { - Span span = this.tracer.nextSpan().name("foo").start(); - final AtomicReference spanInOperation = new AtomicReference<>(); - log.info("Hello"); - - try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { - Mono.just(1).flatMap(d -> Flux.just(d + 1).collectList().map(p -> p.get(0))) - .map(d -> d + 1).map((d) -> { + Flux.from(traced).map(d -> d + 1).map(d -> d + 1).map((d) -> { spanInOperation.set(this.tracer.currentSpan()); return d + 1; }).map(d -> d + 1).subscribe(System.out::println); - } finally { + } + finally { span.finish(); } @@ -97,14 +74,37 @@ public class SpanSubscriberTests { then(spanInOperation.get().context().spanId()).isEqualTo(span.context().spanId()); } - @Test public void should_not_trace_scalar_flows() { + @Test + public void should_support_reactor_fusion_optimization() { + Span span = this.tracer.nextSpan().name("foo").start(); + final AtomicReference spanInOperation = new AtomicReference<>(); + log.info("Hello"); + + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { + Mono.just(1).flatMap(d -> Flux.just(d + 1).collectList().map(p -> p.get(0))) + .map(d -> d + 1).map((d) -> { + spanInOperation.set(this.tracer.currentSpan()); + return d + 1; + }).map(d -> d + 1).subscribe(System.out::println); + } + finally { + span.finish(); + } + + then(this.tracer.currentSpan()).isNull(); + then(spanInOperation.get().context().spanId()).isEqualTo(span.context().spanId()); + } + + @Test + public void should_not_trace_scalar_flows() { Span span = this.tracer.nextSpan().name("foo").start(); final AtomicReference spanInOperation = new AtomicReference<>(); log.info("Hello"); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { Mono.just(1).subscribe(new BaseSubscriber() { - @Override protected void hookOnSubscribe(Subscription subscription) { + @Override + protected void hookOnSubscribe(Subscription subscription) { spanInOperation.set(subscription); } }); @@ -112,32 +112,31 @@ public class SpanSubscriberTests { then(this.tracer.currentSpan()).isNotNull(); then(spanInOperation.get()).isInstanceOf(ScopePassingSpanSubscriber.class); - Mono.error(new Exception()) - .subscribe(new BaseSubscriber() { - @Override - protected void hookOnSubscribe(Subscription subscription) { - spanInOperation.set(subscription); - } + Mono.error(new Exception()).subscribe(new BaseSubscriber() { + @Override + protected void hookOnSubscribe(Subscription subscription) { + spanInOperation.set(subscription); + } - @Override - protected void hookOnError(Throwable throwable) { - } - }); + @Override + protected void hookOnError(Throwable throwable) { + } + }); then(this.tracer.currentSpan()).isNotNull(); then(spanInOperation.get()).isInstanceOf(ScopePassingSpanSubscriber.class); - Mono.empty() - .subscribe(new BaseSubscriber() { - @Override - protected void hookOnSubscribe(Subscription subscription) { - spanInOperation.set(subscription); - } - }); + Mono.empty().subscribe(new BaseSubscriber() { + @Override + protected void hookOnSubscribe(Subscription subscription) { + spanInOperation.set(subscription); + } + }); then(this.tracer.currentSpan()).isNotNull(); then(spanInOperation.get()).isEqualTo(Operators.emptySubscription()); - } finally { + } + finally { span.finish(); } @@ -152,17 +151,20 @@ public class SpanSubscriberTests { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { Flux.just(1, 2, 3).publishOn(Schedulers.single()).log("reactor.1") - .map(d -> d + 1).map(d -> d + 1).publishOn(Schedulers.newSingle("secondThread")).log("reactor.2") + .map(d -> d + 1).map(d -> d + 1) + .publishOn(Schedulers.newSingle("secondThread")).log("reactor.2") .map((d) -> { spanInOperation.set(this.tracer.currentSpan()); return d + 1; }).map(d -> d + 1).blockLast(); Awaitility.await().untilAsserted(() -> { - then(spanInOperation.get().context().spanId()).isEqualTo(span.context().spanId()); + then(spanInOperation.get().context().spanId()) + .isEqualTo(span.context().spanId()); }); then(this.tracer.currentSpan()).isEqualTo(span); - } finally { + } + finally { span.finish(); } @@ -170,15 +172,18 @@ public class SpanSubscriberTests { Span foo2 = this.tracer.nextSpan().name("foo").start(); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(foo2)) { - Flux.just(1, 2, 3).publishOn(Schedulers.single()).log("reactor.").map(d -> d + 1).map(d -> d + 1).map((d) -> { - spanInOperation.set(this.tracer.currentSpan()); - return d + 1; - }).map(d -> d + 1).blockLast(); + Flux.just(1, 2, 3).publishOn(Schedulers.single()).log("reactor.") + .map(d -> d + 1).map(d -> d + 1).map((d) -> { + spanInOperation.set(this.tracer.currentSpan()); + return d + 1; + }).map(d -> d + 1).blockLast(); then(this.tracer.currentSpan()).isEqualTo(foo2); // parent cause there's an async span in the meantime - then(spanInOperation.get().context().spanId()).isEqualTo(foo2.context().spanId()); - } finally { + then(spanInOperation.get().context().spanId()) + .isEqualTo(foo2.context().spanId()); + } + finally { foo2.finish(); } @@ -191,13 +196,11 @@ public class SpanSubscriberTests { log.info("Hello"); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(parentSpan)) { final Long spanId = Mono.fromCallable(tracer::currentSpan) - .map(span -> span.context().spanId()) - .block(); + .map(span -> span.context().spanId()).block(); then(spanId).isNotNull(); final Long secondSpanId = Mono.fromCallable(tracer::currentSpan) - .map(span -> span.context().spanId()) - .block(); + .map(span -> span.context().spanId()).block(); then(secondSpanId).isEqualTo(spanId); // different trace ids here } } @@ -209,18 +212,20 @@ public class SpanSubscriberTests { final AtomicReference spanInZipOperation = new AtomicReference<>(); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initSpan)) { - Mono.fromCallable(tracer::currentSpan) - .map(span -> span.context().spanId()) + Mono.fromCallable(tracer::currentSpan).map(span -> span.context().spanId()) .doOnNext(spanInOperation::set) - .zipWith( - Mono.fromCallable(tracer::currentSpan) - .map(span -> span.context().spanId()) - .doOnNext(spanInZipOperation::set)) + .zipWith(Mono.fromCallable(tracer::currentSpan) + .map(span -> span.context().spanId()) + .doOnNext(spanInZipOperation::set)) .block(); } then(spanInZipOperation).hasValue(initSpan.context().spanId()); // ok here - then(spanInOperation).hasValue(initSpan.context().spanId()); // Expecting to have value: <1L> but did not. + then(spanInOperation).hasValue(initSpan.context().spanId()); // Expecting + // + // to have value: + // <1L> but did + // not. } // #646 @@ -230,12 +235,13 @@ public class SpanSubscriberTests { log.info("Hello"); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initSpan)) { - Mono.just("value1").flatMap(request -> Mono.just("value2").then(Mono.just("foo"))) + Mono.just("value1") + .flatMap(request -> Mono.just("value2").then(Mono.just("foo"))) .map(a -> "qwe").block(); } } - //#1030 + // #1030 @Test public void checkTraceIdFromSubscriberContext() { Span initSpan = this.tracer.nextSpan().name("foo").start(); @@ -244,8 +250,7 @@ public class SpanSubscriberTests { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initSpan)) { Mono.subscriberContext() .map(context -> tracer.currentSpan().context().spanId()) - .doOnNext(spanInSubscriberContext::set) - .block(); + .doOnNext(spanInSubscriberContext::set).block(); } then(spanInSubscriberContext).hasValue(initSpan.context().spanId()); // ok here @@ -260,8 +265,12 @@ public class SpanSubscriberTests { @EnableAutoConfiguration @Configuration static class Config { - @Bean Sampler sampler() { + + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/sample/FlatMapTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/sample/FlatMapTests.java index afad25a50..b2bbcad94 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/sample/FlatMapTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/sample/FlatMapTests.java @@ -71,18 +71,23 @@ public class FlatMapTests { Issue866Configuration.hook = null; } - @Rule public OutputCapture capture = new OutputCapture(); + @Rule + public OutputCapture capture = new OutputCapture(); - @Test public void should_work_with_flat_maps() { - //given + @Test + public void should_work_with_flat_maps() { + // given ConfigurableApplicationContext context = new SpringApplicationBuilder( FlatMapTests.TestConfiguration.class, Issue866Configuration.class) - .web(WebApplicationType.REACTIVE) - .properties("server.port=0", "spring.jmx.enabled=false", - "spring.application.name=TraceWebFluxTests", "security.basic.enabled=false", - "management.security.enabled=false").run(); + .web(WebApplicationType.REACTIVE) + .properties("server.port=0", "spring.jmx.enabled=false", + "spring.application.name=TraceWebFluxTests", + "security.basic.enabled=false", + "management.security.enabled=false") + .run(); ArrayListSpanReporter accumulator = context.getBean(ArrayListSpanReporter.class); - int port = context.getBean(Environment.class).getProperty("local.server.port", Integer.class); + int port = context.getBean(Environment.class).getProperty("local.server.port", + Integer.class); RequestSender sender = context.getBean(RequestSender.class); TestConfiguration config = context.getBean(TestConfiguration.class); FactoryUser factoryUser = context.getBean(FactoryUser.class); @@ -90,29 +95,27 @@ public class FlatMapTests { accumulator.clear(); Awaitility.await().untilAsserted(() -> { - //when + // when accumulator.clear(); String firstTraceId = flatMapTraceId(accumulator, callFlatMap(port).block()); - //then + // then thenAllWebClientCallsHaveSameTraceId(firstTraceId, sender); thenSpanInFooHasSameTraceId(firstTraceId, config); accumulator.clear(); - //when + // when String secondTraceId = flatMapTraceId(accumulator, callFlatMap(port).block()); - //then - then(firstTraceId) - .as("Id will not be reused between calls") + // then + then(firstTraceId).as("Id will not be reused between calls") .isNotEqualTo(secondTraceId); thenSpanInFooHasSameTraceId(secondTraceId, config); - //and + // and then(Arrays.stream(capture.toString().split("\n")) .filter(s -> s.contains("Received a request to uri")) - .map(s -> s.split(",")[1]) - .collect(Collectors.toList())) - .as("TracingFilter should not have any trace when receiving a request") - .containsOnly(""); - //and #866 + .map(s -> s.split(",")[1]).collect(Collectors.toList())).as( + "TracingFilter should not have any trace when receiving a request") + .containsOnly(""); + // and #866 then(factoryUser.wasSchedulerWrapped).isTrue(); }); } @@ -122,14 +125,13 @@ public class FlatMapTests { then(sender.span.context().traceIdString()).isEqualTo(traceId); } - private void thenSpanInFooHasSameTraceId(String traceId, - TestConfiguration config) { + private void thenSpanInFooHasSameTraceId(String traceId, TestConfiguration config) { then(config.spanInFoo.context().traceIdString()).isEqualTo(traceId); } private Mono callFlatMap(int port) { - return WebClient.create().get() - .uri("http://localhost:" + port + "/withFlatMap").exchange(); + return WebClient.create().get().uri("http://localhost:" + port + "/withFlatMap") + .exchange(); } private String flatMapTraceId(ArrayListSpanReporter accumulator, @@ -138,9 +140,9 @@ public class FlatMapTests { then(accumulator.getSpans()).isNotEmpty(); LOGGER.info("Accumulated spans: " + accumulator.getSpans()); List traceIdOfFlatMap = accumulator.getSpans().stream() - .filter(span -> span.tags().containsKey("http.path") && span.tags() - .get("http.path").equals("/withFlatMap")).map(Span::traceId) - .collect(Collectors.toList()); + .filter(span -> span.tags().containsKey("http.path") + && span.tags().get("http.path").equals("/withFlatMap")) + .map(Span::traceId).collect(Collectors.toList()); then(traceIdOfFlatMap).hasSize(1); return traceIdOfFlatMap.get(0); } @@ -152,7 +154,9 @@ public class FlatMapTests { brave.Span spanInFoo; - @Bean RouterFunction handlers(Tracer tracer, RequestSender requestSender) { + @Bean + RouterFunction handlers(Tracer tracer, + RequestSender requestSender) { return route(GET("/noFlatMap"), request -> { LOGGER.info("noFlatMap"); Flux one = requestSender.getAll().map(String::length); @@ -160,8 +164,9 @@ public class FlatMapTests { }).andRoute(GET("/withFlatMap"), request -> { LOGGER.info("withFlatMap"); Flux one = requestSender.getAll().map(String::length); - Flux response = one.flatMap(size -> requestSender.getAll() - .doOnEach(sig -> LOGGER.info(sig.getContext().toString()))) + Flux response = one + .flatMap(size -> requestSender.getAll().doOnEach( + sig -> LOGGER.info(sig.getContext().toString()))) .map(string -> { LOGGER.info("WHATEVER YEAH"); return string.length(); @@ -174,19 +179,23 @@ public class FlatMapTests { }); } - @Bean WebClient webClient() { + @Bean + WebClient webClient() { return WebClient.create(); } - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean RequestSender sender(WebClient client, Tracer tracer) { + @Bean + RequestSender sender(WebClient client, Tracer tracer) { return new RequestSender(client, tracer); } @@ -197,13 +206,16 @@ public class FlatMapTests { } } + } class FactoryUser { + boolean wasSchedulerWrapped = false; FactoryUser() { Issue866Configuration.TestHook hook = Issue866Configuration.hook; this.wasSchedulerWrapped = hook != null && hook.executed; } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/sample/RequestSender.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/sample/RequestSender.java index 525ea73fc..f297842e0 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/sample/RequestSender.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/reactor/sample/RequestSender.java @@ -27,33 +27,34 @@ import reactor.core.publisher.Mono; class RequestSender { - private static final Logger LOGGER = LoggerFactory.getLogger(RequestSender.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RequestSender.class); - private final WebClient webClient; - private final Tracer tracer; - int port; - Span span; + private final WebClient webClient; - public RequestSender(WebClient webClient, Tracer tracer) { - this.webClient = webClient; - this.tracer = tracer; - } + private final Tracer tracer; - public Mono get(Integer someParameterNotUsedNow){ - LOGGER.info("getting for parameter {}", someParameterNotUsedNow); - this.span = this.tracer.currentSpan(); - return webClient - .method(HttpMethod.GET) - .uri("http://localhost:" + this.port + "/foo") - .retrieve().bodyToMono(String.class); - } + int port; - public Flux getAll(){ - LOGGER.info("Before merge"); - Flux merge = Flux.merge(get(1), get(2), get(3)); - LOGGER.info("after merge"); - return merge; - } + Span span; + public RequestSender(WebClient webClient, Tracer tracer) { + this.webClient = webClient; + this.tracer = tracer; + } + + public Mono get(Integer someParameterNotUsedNow) { + LOGGER.info("getting for parameter {}", someParameterNotUsedNow); + this.span = this.tracer.currentSpan(); + return webClient.method(HttpMethod.GET) + .uri("http://localhost:" + this.port + "/foo").retrieve() + .bodyToMono(String.class); + } + + public Flux getAll() { + LOGGER.info("Before merge"); + Flux merge = Flux.merge(get(1), get(2), get(3)); + LOGGER.info("after merge"); + return merge; + } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHookTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHookTests.java index 24c1621e9..2eeadc366 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHookTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHookTests.java @@ -43,19 +43,19 @@ import org.springframework.cloud.sleuth.util.ArrayListSpanReporter; import static org.assertj.core.api.BDDAssertions.then; /** - * * @author Shivang Shah */ public class SleuthRxJavaSchedulersHookTests { List threadsToIgnore = new ArrayList<>(); + ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + Tracer tracer = this.tracing.tracer(); @After @@ -63,6 +63,7 @@ public class SleuthRxJavaSchedulersHookTests { this.tracing.close(); this.reporter.clear(); } + private static StringBuilder caller; @Before @@ -75,19 +76,22 @@ public class SleuthRxJavaSchedulersHookTests { @Test public void should_not_override_existing_custom_hooks() { RxJavaPlugins.getInstance().registerErrorHandler(new MyRxJavaErrorHandler()); - RxJavaPlugins.getInstance().registerObservableExecutionHook(new MyRxJavaObservableExecutionHook()); + RxJavaPlugins.getInstance() + .registerObservableExecutionHook(new MyRxJavaObservableExecutionHook()); new SleuthRxJavaSchedulersHook(this.tracer, threadsToIgnore); - then(RxJavaPlugins.getInstance().getErrorHandler()).isExactlyInstanceOf(MyRxJavaErrorHandler.class); - then(RxJavaPlugins.getInstance().getObservableExecutionHook()).isExactlyInstanceOf(MyRxJavaObservableExecutionHook.class); + then(RxJavaPlugins.getInstance().getErrorHandler()) + .isExactlyInstanceOf(MyRxJavaErrorHandler.class); + then(RxJavaPlugins.getInstance().getObservableExecutionHook()) + .isExactlyInstanceOf(MyRxJavaObservableExecutionHook.class); } @Test public void should_wrap_delegates_action_in_wrapped_action_when_delegate_is_present_on_schedule() { RxJavaPlugins.getInstance().registerSchedulersHook(new MyRxJavaSchedulersHook()); SleuthRxJavaSchedulersHook schedulersHook = new SleuthRxJavaSchedulersHook( - this.tracer, this.threadsToIgnore); + this.tracer, this.threadsToIgnore); Action0 action = schedulersHook.onSchedule(() -> { caller = new StringBuilder("hello"); }); @@ -106,7 +110,7 @@ public class SleuthRxJavaSchedulersHookTests { String threadNameToIgnore = "^MyCustomThread.*$"; RxJavaPlugins.getInstance().registerSchedulersHook(new MyRxJavaSchedulersHook()); SleuthRxJavaSchedulersHook schedulersHook = new SleuthRxJavaSchedulersHook( - this.tracer, Collections.singletonList(threadNameToIgnore)); + this.tracer, Collections.singletonList(threadNameToIgnore)); Future hello = executorService().submit((Callable) () -> { Action0 action = schedulersHook.onSchedule(() -> { caller = new StringBuilder("hello"); @@ -127,11 +131,11 @@ public class SleuthRxJavaSchedulersHookTests { thread.setName("MyCustomThread10"); return thread; }; - return Executors - .newSingleThreadExecutor(threadFactory); + return Executors.newSingleThreadExecutor(threadFactory); } static class MyRxJavaObservableExecutionHook extends RxJavaObservableExecutionHook { + } static class MyRxJavaSchedulersHook extends RxJavaSchedulersHook { @@ -142,8 +146,11 @@ public class SleuthRxJavaSchedulersHookTests { caller = new StringBuilder("called_from_schedulers_hook"); }; } + } static class MyRxJavaErrorHandler extends RxJavaErrorHandler { + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaTests.java index 15b478d6f..2b1ddfd5f 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaTests.java @@ -48,8 +48,10 @@ public class SleuthRxJavaTests { @Autowired ArrayListSpanReporter reporter; + @Autowired Tracer tracer; + StringBuffer caller = new StringBuffer(); @Before @@ -85,12 +87,12 @@ public class SleuthRxJavaTests { Span spanInCurrentThread = this.tracer.nextSpan().name("current_span"); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(spanInCurrentThread)) { - Observable - .defer(() -> Observable.just( - (Action0) () -> this.caller = new StringBuffer("actual_action"))) + Observable.defer(() -> Observable.just( + (Action0) () -> this.caller = new StringBuffer("actual_action"))) .subscribeOn(Schedulers.newThread()).toBlocking() .subscribe(Action0::call); - } finally { + } + finally { spanInCurrentThread.finish(); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/scheduling/TracingOnScheduledTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/scheduling/TracingOnScheduledTests.java index 856645c08..b7ea48a38 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/scheduling/TracingOnScheduledTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/scheduling/TracingOnScheduledTests.java @@ -48,9 +48,14 @@ import static org.awaitility.Awaitility.await; @DirtiesContext public class TracingOnScheduledTests { - @Autowired TestBeanWithScheduledMethod beanWithScheduledMethod; - @Autowired TestBeanWithScheduledMethodToBeIgnored beanWithScheduledMethodToBeIgnored; - @Autowired ArrayListSpanReporter reporter; + @Autowired + TestBeanWithScheduledMethod beanWithScheduledMethod; + + @Autowired + TestBeanWithScheduledMethodToBeIgnored beanWithScheduledMethodToBeIgnored; + + @Autowired + ArrayListSpanReporter reporter; @Before public void setup() { @@ -60,7 +65,7 @@ public class TracingOnScheduledTests { @Test public void should_have_span_set_after_scheduled_method_has_been_executed() { - await().atMost( 10, SECONDS).untilAsserted(() -> { + await().atMost(10, SECONDS).untilAsserted(() -> { then(this.beanWithScheduledMethod.isExecuted()).isTrue(); spanIsSetOnAScheduledMethod(); }); @@ -85,13 +90,12 @@ public class TracingOnScheduledTests { } private void spanIsSetOnAScheduledMethod() { - Span storedSpan = TracingOnScheduledTests.this.beanWithScheduledMethod - .getSpan(); + Span storedSpan = TracingOnScheduledTests.this.beanWithScheduledMethod.getSpan(); then(storedSpan).isNotNull(); then(storedSpan.context().traceId()).isNotNull(); - then(this.reporter.getSpans().get(0).tags()) - .contains(new AbstractMap.SimpleEntry<>("class", "TestBeanWithScheduledMethod"), - new AbstractMap.SimpleEntry<>("method", "scheduledMethod")); + then(this.reporter.getSpans().get(0).tags()).contains( + new AbstractMap.SimpleEntry<>("class", "TestBeanWithScheduledMethod"), + new AbstractMap.SimpleEntry<>("method", "scheduledMethod")); then(this.reporter.getSpans().get(0).durationAsLong()).isGreaterThan(0L); } @@ -107,19 +111,24 @@ public class TracingOnScheduledTests { @EnableScheduling class ScheduledTestConfiguration { - @Bean Reporter testRepoter() { + @Bean + Reporter testRepoter() { return new ArrayListSpanReporter(); } - @Bean TestBeanWithScheduledMethod testBeanWithScheduledMethod(Tracing tracing) { + @Bean + TestBeanWithScheduledMethod testBeanWithScheduledMethod(Tracing tracing) { return new TestBeanWithScheduledMethod(tracing); } - @Bean TestBeanWithScheduledMethodToBeIgnored testBeanWithScheduledMethodToBeIgnored(Tracing tracing) { + @Bean + TestBeanWithScheduledMethodToBeIgnored testBeanWithScheduledMethodToBeIgnored( + Tracing tracing) { return new TestBeanWithScheduledMethodToBeIgnored(tracing); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } @@ -159,6 +168,7 @@ class TestBeanWithScheduledMethod { this.span = null; this.executed.set(false); } + } class TestBeanWithScheduledMethodToBeIgnored { @@ -166,6 +176,7 @@ class TestBeanWithScheduledMethodToBeIgnored { private final Tracing tracing; Span span; + AtomicBoolean executed = new AtomicBoolean(false); TestBeanWithScheduledMethodToBeIgnored(Tracing tracing) { @@ -189,4 +200,5 @@ class TestBeanWithScheduledMethodToBeIgnored { public void clear() { this.executed.set(false); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/AbstractMvcIntegrationTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/AbstractMvcIntegrationTest.java index 40a39b9f5..4a314d9ec 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/AbstractMvcIntegrationTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/AbstractMvcIntegrationTest.java @@ -28,26 +28,32 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; /** - * Base for specifications that use Spring's {@link MockMvc}. Provides also {@link WebApplicationContext}, - * {@link ApplicationContext}. The latter you can use to specify what - * kind of address should be returned for a given dependency name. + * Base for specifications that use Spring's {@link MockMvc}. Provides also + * {@link WebApplicationContext}, {@link ApplicationContext}. The latter you can use to + * specify what kind of address should be returned for a given dependency name. * * @see WebApplicationContext * @see ApplicationContext - * * @author 4financeIT */ @WebAppConfiguration public abstract class AbstractMvcIntegrationTest { - @Autowired protected WebApplicationContext webApplicationContext; + @Autowired + protected WebApplicationContext webApplicationContext; + protected MockMvc mockMvc; - @Autowired protected SleuthProperties properties; - @Autowired protected Tracing tracing; + + @Autowired + protected SleuthProperties properties; + + @Autowired + protected Tracing tracing; @Before public void setup() { - DefaultMockMvcBuilder mockMvcBuilder = MockMvcBuilders.webAppContextSetup(this.webApplicationContext); + DefaultMockMvcBuilder mockMvcBuilder = MockMvcBuilders + .webAppContextSetup(this.webApplicationContext); configureMockMvcBuilder(mockMvcBuilder); this.mockMvc = mockMvcBuilder.build(); } @@ -59,4 +65,5 @@ public abstract class AbstractMvcIntegrationTest { */ protected void configureMockMvcBuilder(DefaultMockMvcBuilder mockMvcBuilder) { } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/CompositeHttpSamplerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/CompositeHttpSamplerTests.java index 59a3567a9..72829254b 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/CompositeHttpSamplerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/CompositeHttpSamplerTests.java @@ -30,13 +30,18 @@ import static org.mockito.BDDMockito.given; @RunWith(MockitoJUnitRunner.class) public class CompositeHttpSamplerTests { - @Mock HttpAdapter adapter; - @Mock HttpSampler left, right; + @Mock + HttpAdapter adapter; + + @Mock + HttpSampler left, right; + HttpSampler sampler; + Object request = new Object(); @Before - public void init(){ + public void init() { this.sampler = new CompositeHttpSampler(left, right); } @@ -78,4 +83,5 @@ public class CompositeHttpSamplerTests { then(this.sampler.trySample(this.adapter, this.request)).isTrue(); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java index c1b3a81c2..022e2191f 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java @@ -35,27 +35,31 @@ public class SkipPatternProviderConfigTest { public void should_pick_skip_pattern_from_sleuth_properties() throws Exception { SleuthWebProperties sleuthWebProperties = new SleuthWebProperties(); sleuthWebProperties.setSkipPattern("foo.*|bar.*"); - Pattern pattern = new TraceWebAutoConfiguration.DefaultSkipPatternConfig().defaultSkipPatternBean(sleuthWebProperties) - .skipPattern().get(); + Pattern pattern = new TraceWebAutoConfiguration.DefaultSkipPatternConfig() + .defaultSkipPatternBean(sleuthWebProperties).skipPattern().get(); then(pattern.pattern()).isEqualTo("foo.*|bar.*"); } @Test - public void should_combine_skip_pattern_and_additional_pattern_when_all_are_not_empty() throws Exception { + public void should_combine_skip_pattern_and_additional_pattern_when_all_are_not_empty() + throws Exception { SleuthWebProperties sleuthWebProperties = new SleuthWebProperties(); sleuthWebProperties.setSkipPattern("foo.*|bar.*"); sleuthWebProperties.setAdditionalSkipPattern("baz.*|faz.*"); - Pattern pattern = new TraceWebAutoConfiguration.DefaultSkipPatternConfig().defaultSkipPatternBean(sleuthWebProperties) - .skipPattern().get(); + Pattern pattern = new TraceWebAutoConfiguration.DefaultSkipPatternConfig() + .defaultSkipPatternBean(sleuthWebProperties).skipPattern().get(); then(pattern.pattern()).isEqualTo("foo.*|bar.*|baz.*|faz.*"); } @Test - public void should_return_empty_when_management_context_has_no_context_path() throws Exception { + public void should_return_empty_when_management_context_has_no_context_path() + throws Exception { Optional pattern = new TraceWebAutoConfiguration.ManagementSkipPatternProviderConfig() - .skipPatternForManagementServerProperties(new ManagementServerProperties()).skipPattern(); + .skipPatternForManagementServerProperties( + new ManagementServerProperties()) + .skipPattern(); then(pattern).isEmpty(); } @@ -73,7 +77,8 @@ public class SkipPatternProviderConfigTest { } @Test - public void should_return_empty_when_server_props_have_no_context_path() throws Exception { + public void should_return_empty_when_server_props_have_no_context_path() + throws Exception { Optional pattern = new TraceWebAutoConfiguration.ServerSkipPatternProviderConfig() .skipPatternForServerProperties(new ServerProperties()).skipPattern(); @@ -109,4 +114,5 @@ public class SkipPatternProviderConfigTest { private SingleSkipPattern bar() { return () -> Optional.of(Pattern.compile("bar")); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpClientParserTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpClientParserTests.java index 3e736227d..20b794ce3 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpClientParserTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpClientParserTests.java @@ -30,64 +30,77 @@ import brave.http.HttpClientAdapter; /** * Test case for HttpTraceKeysInjector - * + * * @author Sven Zethelius */ public class SleuthHttpClientParserTests { + private TraceKeys traceKeys = new TraceKeys(); + private TestSpanCustomizer customizer = new TestSpanCustomizer(); + private SleuthHttpClientParser parser = new SleuthHttpClientParser(this.traceKeys); @Test public void should_set_tags_on_span_with_proper_header_values() throws Exception { - this.traceKeys.getHttp().setHeaders(Arrays.asList("Accept", "User-Agent", "Content-Type")); + this.traceKeys.getHttp() + .setHeaders(Arrays.asList("Accept", "User-Agent", "Content-Type")); this.parser.request(new HttpClientAdapter() { private final URL url = new URL("http://localhost:8080/"); - @Override public String method(Object request) { + @Override + public String method(Object request) { return "GET"; } - @Override public String url(Object request) { + @Override + public String url(Object request) { return url.toString(); } - @Override public String requestHeader(Object request, String name) { + @Override + public String requestHeader(Object request, String name) { if (name.equals("Accept")) { return "'text/plain','text/xml'"; - } else if (name.equals("User-Agent")) { + } + else if (name.equals("User-Agent")) { return "Test"; } return null; } - @Override public Integer statusCode(Object response) { + @Override + public Integer statusCode(Object response) { return 200; } }, null, this.customizer); - then(this.customizer.tags) - .containsEntry("http.user-agent", "Test") - .containsEntry("http.accept", "'text/plain','text/xml'") - .doesNotContainKey("http.content-type"); + then(this.customizer.tags).containsEntry("http.user-agent", "Test") + .containsEntry("http.accept", "'text/plain','text/xml'") + .doesNotContainKey("http.content-type"); } + } class TestSpanCustomizer implements SpanCustomizer { Map tags = new HashMap<>(); - @Override public SpanCustomizer name(String name) { + @Override + public SpanCustomizer name(String name) { return this; } - @Override public SpanCustomizer tag(String key, String value) { + @Override + public SpanCustomizer tag(String key, String value) { this.tags.put(key, value); return this; } - @Override public SpanCustomizer annotate(String value) { + @Override + public SpanCustomizer annotate(String value) { return this; } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpParserAccessor.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpParserAccessor.java index 63f27bee0..c7496631e 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpParserAccessor.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpParserAccessor.java @@ -25,6 +25,7 @@ import brave.http.HttpServerParser; * @since */ public class SleuthHttpParserAccessor { + public static HttpClientParser getClient() { return new SleuthHttpClientParser(new TraceKeys()); } @@ -32,4 +33,5 @@ public class SleuthHttpParserAccessor { public static HttpServerParser getServer(ErrorParser errorParser) { return new SleuthHttpServerParser(new TraceKeys(), errorParser); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpSamplerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpSamplerTests.java index bb2548496..d4b72658b 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpSamplerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SleuthHttpSamplerTests.java @@ -33,7 +33,8 @@ import static org.assertj.core.api.BDDAssertions.then; @RunWith(MockitoJUnitRunner.class) public class SleuthHttpSamplerTests { - @Mock HttpAdapter adapter; + @Mock + HttpAdapter adapter; @Test public void should_delegate_sampling_decision_if_pattern_is_not_matched() { @@ -52,4 +53,5 @@ public class SleuthHttpSamplerTests { then(sampler.trySample(this.adapter, new Object())).isFalse(); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SpringDataInstrumentationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SpringDataInstrumentationTests.java index d750e3cb2..73e6c1646 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SpringDataInstrumentationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SpringDataInstrumentationTests.java @@ -55,19 +55,20 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = ReservationServiceApplication.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = "spring.sleuth.http.legacy.enabled=true") +@SpringBootTest(classes = ReservationServiceApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "spring.sleuth.http.legacy.enabled=true") @DirtiesContext @ActiveProfiles("data") public class SpringDataInstrumentationTests { @Autowired RestTemplate restTemplate; + @Autowired Environment environment; + @Autowired Tracer tracer; + @Autowired ArrayListSpanReporter reporter; @@ -85,25 +86,28 @@ public class SpringDataInstrumentationTests { Awaitility.await().untilAsserted(() -> { // Make sure the data is attached to the right side of the span then(this.reporter.getSpans()) - .extracting(Span::kind, Span::name, s -> s.tags().get("mvc.controller.class")) + .extracting(Span::kind, Span::name, + s -> s.tags().get("mvc.controller.class")) .containsExactlyInAnyOrder( tuple(Span.Kind.CLIENT, "http:/reservations", null), - tuple(Span.Kind.SERVER, "http:/reservations", "RepositoryEntityController") - ); + tuple(Span.Kind.SERVER, "http:/reservations", + "RepositoryEntityController")); }); then(this.tracer.currentSpan()).isNull(); } long namesCount() { - return - this.restTemplate.exchange(RequestEntity - .get(URI.create("http://localhost:" + port() + "/reservations")).build(), PagedResources.class) + return this.restTemplate + .exchange(RequestEntity + .get(URI.create("http://localhost:" + port() + "/reservations")) + .build(), PagedResources.class) .getBody().getMetadata().getTotalElements(); } private int port() { return this.environment.getProperty("local.server.port", Integer.class); } + } @Configuration @@ -116,8 +120,8 @@ class ReservationServiceApplication { return new RestTemplate(); } - @Bean SampleRecords sampleRecords( - ReservationRepository reservationRepository) { + @Bean + SampleRecords sampleRecords(ReservationRepository reservationRepository) { return new SampleRecords(reservationRepository); } @@ -137,8 +141,7 @@ class SampleRecords { private final ReservationRepository reservationRepository; - public SampleRecords( - ReservationRepository reservationRepository) { + public SampleRecords(ReservationRepository reservationRepository) { this.reservationRepository = reservationRepository; } @@ -149,10 +152,12 @@ class SampleRecords { .forEach(name -> reservationRepository.save(new Reservation(name))); reservationRepository.findAll().forEach(System.out::println); } + } @RepositoryRestResource interface ReservationRepository extends JpaRepository { + } @Entity @@ -185,4 +190,5 @@ class Reservation { this.reservationName = reservationName; } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceAsyncIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceAsyncIntegrationTests.java index 876fcbf6a..ee8c58c00 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceAsyncIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceAsyncIntegrationTests.java @@ -43,14 +43,15 @@ import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringRunner.class) @SpringBootTest(classes = { - TraceAsyncIntegrationTests.TraceAsyncITestConfiguration.class }, - properties = "spring.sleuth.http.legacy.enabled=true") + TraceAsyncIntegrationTests.TraceAsyncITestConfiguration.class }, properties = "spring.sleuth.http.legacy.enabled=true") public class TraceAsyncIntegrationTests { @Autowired ClassPerformingAsyncLogic classPerformingAsyncLogic; + @Autowired Tracer tracer; + @Autowired ArrayListSpanReporter reporter; @@ -80,7 +81,8 @@ public class TraceAsyncIntegrationTests { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { whenAsyncProcessingTakesPlace(); - } finally { + } + finally { span.finish(); } @@ -93,7 +95,8 @@ public class TraceAsyncIntegrationTests { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { whenAsyncProcessingTakesPlaceWithCustomSpanName(); - } finally { + } + finally { span.finish(); } @@ -113,61 +116,56 @@ public class TraceAsyncIntegrationTests { } private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOne(final Span span) { - Awaitility.await().atMost(5, SECONDS).untilAsserted( - () -> { - then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic - .getSpan().context().traceId()).isEqualTo(span.context().traceId()); - then(this.reporter.getSpans()).hasSize(2); - // HTTP - then(this.reporter.getSpans().get(0).name()).isEqualTo("http:existing"); - // ASYNC - then(this.reporter.getSpans().get(1).tags()) - .containsEntry("class", "ClassPerformingAsyncLogic") - .containsEntry("method", "invokeAsynchronousLogic"); - }); + Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> { + then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan() + .context().traceId()).isEqualTo(span.context().traceId()); + then(this.reporter.getSpans()).hasSize(2); + // HTTP + then(this.reporter.getSpans().get(0).name()).isEqualTo("http:existing"); + // ASYNC + then(this.reporter.getSpans().get(1).tags()) + .containsEntry("class", "ClassPerformingAsyncLogic") + .containsEntry("method", "invokeAsynchronousLogic"); + }); } private void thenANewAsyncSpanGetsCreated() { - Awaitility.await().atMost(5, SECONDS).untilAsserted( - () -> { - then(this.reporter.getSpans()).hasSize(1); - zipkin2.Span storedSpan = this.reporter.getSpans().get(0); - then(storedSpan.name()).isEqualTo("invoke-asynchronous-logic"); - then(storedSpan.tags()) - .containsEntry("class", "ClassPerformingAsyncLogic") - .containsEntry("method", "invokeAsynchronousLogic"); - }); + Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> { + then(this.reporter.getSpans()).hasSize(1); + zipkin2.Span storedSpan = this.reporter.getSpans().get(0); + then(storedSpan.name()).isEqualTo("invoke-asynchronous-logic"); + then(storedSpan.tags()).containsEntry("class", "ClassPerformingAsyncLogic") + .containsEntry("method", "invokeAsynchronousLogic"); + }); } - private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName(final Span span) { - Awaitility.await().atMost(5, SECONDS).untilAsserted( - () -> { - then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic - .getSpan().context().traceId()).isEqualTo(span.context().traceId()); - then(this.reporter.getSpans()).hasSize(2); - // HTTP - then(this.reporter.getSpans().get(0).name()).isEqualTo("http:existing"); - // ASYNC - then(this.reporter.getSpans().get(1).tags()) - .containsEntry("class", "ClassPerformingAsyncLogic") - .containsEntry("method", "customNameInvokeAsynchronousLogic"); - }); + private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName( + final Span span) { + Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> { + then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan() + .context().traceId()).isEqualTo(span.context().traceId()); + then(this.reporter.getSpans()).hasSize(2); + // HTTP + then(this.reporter.getSpans().get(0).name()).isEqualTo("http:existing"); + // ASYNC + then(this.reporter.getSpans().get(1).tags()) + .containsEntry("class", "ClassPerformingAsyncLogic") + .containsEntry("method", "customNameInvokeAsynchronousLogic"); + }); } private void thenAsyncSpanHasCustomName() { - Awaitility.await().atMost(5, SECONDS).untilAsserted( - () -> { - then(this.reporter.getSpans()).hasSize(1); - zipkin2.Span storedSpan = this.reporter.getSpans().get(0); - then(storedSpan.name()).isEqualTo("foo"); - then(storedSpan.tags()) - .containsEntry("class", "ClassPerformingAsyncLogic") - .containsEntry("method", "customNameInvokeAsynchronousLogic"); - }); + Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> { + then(this.reporter.getSpans()).hasSize(1); + zipkin2.Span storedSpan = this.reporter.getSpans().get(0); + then(storedSpan.name()).isEqualTo("foo"); + then(storedSpan.tags()).containsEntry("class", "ClassPerformingAsyncLogic") + .containsEntry("method", "customNameInvokeAsynchronousLogic"); + }); } @After - public void cleanTrace(){ + public void cleanTrace() { this.reporter.clear(); } @@ -221,5 +219,7 @@ public class TraceAsyncIntegrationTests { public void clear() { this.span.set(null); } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceCustomFilterResponseInjectorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceCustomFilterResponseInjectorTests.java index 412d95e02..48bd3e9b3 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceCustomFilterResponseInjectorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceCustomFilterResponseInjectorTests.java @@ -52,17 +52,22 @@ import org.springframework.web.filter.GenericFilterBean; import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = TraceCustomFilterResponseInjectorTests.Config.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(classes = TraceCustomFilterResponseInjectorTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @DirtiesContext public class TraceCustomFilterResponseInjectorTests { + static final String TRACE_ID_NAME = "X-B3-TraceId"; static final String SPAN_ID_NAME = "X-B3-SpanId"; - - @Autowired RestTemplate restTemplate; - @Autowired Config config; - @Autowired CustomRestController customRestController; - + + @Autowired + RestTemplate restTemplate; + + @Autowired + Config config; + + @Autowired + CustomRestController customRestController; + @Test @SuppressWarnings("unchecked") public void should_inject_trace_and_span_ids_in_response_headers() { @@ -71,22 +76,23 @@ public class TraceCustomFilterResponseInjectorTests { .build(); @SuppressWarnings("rawtypes") - ResponseEntity responseEntity = this.restTemplate.exchange(requestEntity, Map.class); + ResponseEntity responseEntity = this.restTemplate.exchange(requestEntity, + Map.class); - then(responseEntity.getHeaders()) - .containsKeys(TRACE_ID_NAME, SPAN_ID_NAME) + then(responseEntity.getHeaders()).containsKeys(TRACE_ID_NAME, SPAN_ID_NAME) .as("Trace headers must be present in response headers"); } @Configuration @EnableAutoConfiguration - static class Config - implements ApplicationListener { + static class Config implements ApplicationListener { + int port; // tag::configuration[] @Bean - HttpResponseInjectingTraceFilter responseInjectingTraceFilter(HttpTracing httpTracing) { + HttpResponseInjectingTraceFilter responseInjectingTraceFilter( + HttpTracing httpTracing) { return new HttpResponseInjectingTraceFilter(httpTracing); } // end::configuration[] @@ -106,7 +112,6 @@ public class TraceCustomFilterResponseInjectorTests { return new CustomRestController(); } - } // tag::injector[] @@ -119,15 +124,16 @@ public class TraceCustomFilterResponseInjectorTests { } @Override - public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + public void doFilter(ServletRequest request, ServletResponse servletResponse, + FilterChain filterChain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) servletResponse; Span currentSpan = this.httpTracing.tracing().tracer().currentSpan(); - response.addHeader("X-B3-TraceId", - currentSpan.context().traceIdString()); + response.addHeader("X-B3-TraceId", currentSpan.context().traceIdString()); response.addHeader("X-B3-SpanId", SpanUtil.idToHex(currentSpan.context().spanId())); filterChain.doFilter(request, response); } + } // end::injector[] @@ -142,5 +148,7 @@ public class TraceCustomFilterResponseInjectorTests { } return map; } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegrationTests.java index 5adf7924f..746220b48 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegrationTests.java @@ -67,20 +67,26 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringRunner.class) -@SpringBootTest(classes = TraceFilterIntegrationTests.Config.class, -properties = "spring.sleuth.http.legacy.enabled=true") +@SpringBootTest(classes = TraceFilterIntegrationTests.Config.class, properties = "spring.sleuth.http.legacy.enabled=true") public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { + static final String TRACE_ID_NAME = "X-B3-TraceId"; static final String SPAN_ID_NAME = "X-B3-SpanId"; static final String SAMPLED_NAME = "X-B3-Sampled"; - private static Log logger = LogFactory.getLog( - TraceFilterIntegrationTests.class); + private static Log logger = LogFactory.getLog(TraceFilterIntegrationTests.class); - @Autowired TracingFilter traceFilter; - @Autowired MyFilter myFilter; - @Autowired ArrayListSpanReporter reporter; - @Autowired Tracer tracer; + @Autowired + TracingFilter traceFilter; + + @Autowired + MyFilter myFilter; + + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + Tracer tracer; private static Span span; @@ -96,8 +102,7 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { then(this.reporter.getSpans()).hasSize(1); zipkin2.Span span = this.reporter.getSpans().get(0); - then(span.tags()) - .containsKey(TraceWebFilter.MVC_CONTROLLER_CLASS_KEY) + then(span.tags()).containsKey(TraceWebFilter.MVC_CONTROLLER_CLASS_KEY) .containsKey(TraceWebFilter.MVC_CONTROLLER_METHOD_KEY); then(this.tracer.currentSpan()).isNull(); } @@ -142,32 +147,33 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { Long expectedTraceId = new Random().nextLong(); MvcResult mvcResult = whenSentFutureWithTraceId(expectedTraceId); - this.mockMvc.perform(asyncDispatch(mvcResult)) - .andExpect(status().isOk()).andReturn(); + this.mockMvc.perform(asyncDispatch(mvcResult)).andExpect(status().isOk()) + .andReturn(); then(this.tracer.currentSpan()).isNull(); } @Test - public void should_add_a_custom_tag_to_the_span_created_in_controller() throws Exception { + public void should_add_a_custom_tag_to_the_span_created_in_controller() + throws Exception { Long expectedTraceId = new Random().nextLong(); MvcResult mvcResult = whenSentDeferredWithTraceId(expectedTraceId); - this.mockMvc.perform(asyncDispatch(mvcResult)) - .andExpect(status().isOk()).andReturn(); + this.mockMvc.perform(asyncDispatch(mvcResult)).andExpect(status().isOk()) + .andReturn(); Optional taggedSpan = this.reporter.getSpans().stream() .filter(span -> span.tags().containsKey("tag")).findFirst(); then(taggedSpan.isPresent()).isTrue(); - then(taggedSpan.get().tags()) - .containsEntry("tag", "value") + then(taggedSpan.get().tags()).containsEntry("tag", "value") .containsEntry("mvc.controller.method", "deferredMethod") .containsEntry("mvc.controller.class", "TestController"); then(this.tracer.currentSpan()).isNull(); } @Test - public void should_log_tracing_information_when_404_exception_was_thrown() throws Exception { + public void should_log_tracing_information_when_404_exception_was_thrown() + throws Exception { Long expectedTraceId = new Random().nextLong(); whenSentToNonExistentEndpointWithTraceId(expectedTraceId); @@ -175,45 +181,48 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { // it's a span with the same ids then(this.reporter.getSpans()).hasSize(1); zipkin2.Span serverSpan = this.reporter.getSpans().get(0); - then(serverSpan.tags()) - .containsEntry("custom", "tag") + then(serverSpan.tags()).containsEntry("custom", "tag") .containsEntry("http.status_code", "404"); then(this.tracer.currentSpan()).isNull(); } @Test - public void should_log_tracing_information_when_500_exception_was_thrown() throws Exception { + public void should_log_tracing_information_when_500_exception_was_thrown() + throws Exception { Long expectedTraceId = new Random().nextLong(); try { whenSentToExceptionThrowingEndpoint(expectedTraceId); fail("Should fail"); - } catch (NestedServletException e) { + } + catch (NestedServletException e) { then(e).hasRootCauseInstanceOf(RuntimeException.class); } // we need to dump the span cause it's not in TracingFilter since TF // has also error dispatch and the ErrorController would report the span then(this.reporter.getSpans()).hasSize(1); - then(this.reporter.getSpans().get(0).tags()) - .containsEntry("error", "Request processing failed; nested exception is java.lang.RuntimeException"); + then(this.reporter.getSpans().get(0).tags()).containsEntry("error", + "Request processing failed; nested exception is java.lang.RuntimeException"); } @Test - public void should_assume_that_a_request_without_span_and_with_trace_is_a_root_span() throws Exception { + public void should_assume_that_a_request_without_span_and_with_trace_is_a_root_span() + throws Exception { Long expectedTraceId = new Random().nextLong(); whenSentRequestWithTraceIdAndNoSpanId(expectedTraceId); whenSentRequestWithTraceIdAndNoSpanId(expectedTraceId); - then(this.reporter.getSpans().stream().filter(span -> - span.id().equals(span.traceId())) - .findAny().isPresent()).as("a root span exists").isTrue(); + then(this.reporter.getSpans().stream() + .filter(span -> span.id().equals(span.traceId())).findAny().isPresent()) + .as("a root span exists").isTrue(); then(this.tracer.currentSpan()).isNull(); } @Test - public void should_return_custom_response_headers_when_custom_trace_filter_gets_registered() throws Exception { + public void should_return_custom_response_headers_when_custom_trace_filter_gets_registered() + throws Exception { Long expectedTraceId = new Random().nextLong(); MvcResult mvcResult = whenSentPingWithTraceId(expectedTraceId); @@ -252,12 +261,16 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { return sendDeferredWithTraceId(TRACE_ID_NAME, passedTraceId); } - private MvcResult whenSentToNonExistentEndpointWithTraceId(Long passedTraceId) throws Exception { - return sendRequestWithTraceId("/exception/nonExistent", TRACE_ID_NAME, passedTraceId, HttpStatus.NOT_FOUND); + private MvcResult whenSentToNonExistentEndpointWithTraceId(Long passedTraceId) + throws Exception { + return sendRequestWithTraceId("/exception/nonExistent", TRACE_ID_NAME, + passedTraceId, HttpStatus.NOT_FOUND); } - private MvcResult whenSentToExceptionThrowingEndpoint(Long passedTraceId) throws Exception { - return sendRequestWithTraceId("/throwsException", TRACE_ID_NAME, passedTraceId, HttpStatus.INTERNAL_SERVER_ERROR); + private MvcResult whenSentToExceptionThrowingEndpoint(Long passedTraceId) + throws Exception { + return sendRequestWithTraceId("/throwsException", TRACE_ID_NAME, passedTraceId, + HttpStatus.INTERNAL_SERVER_ERROR); } private MvcResult sendPingWithTraceId(String headerName, Long traceId) @@ -287,14 +300,13 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { .andReturn(); } - private MvcResult sendRequestWithTraceId(String path, String headerName, Long traceId, HttpStatus status) - throws Exception { + private MvcResult sendRequestWithTraceId(String path, String headerName, Long traceId, + HttpStatus status) throws Exception { return this.mockMvc .perform(MockMvcRequestBuilders.get(path).accept(MediaType.TEXT_PLAIN) .header(headerName, SpanUtil.idToHex(traceId)) .header(SPAN_ID_NAME, SpanUtil.idToHex(new Random().nextLong()))) - .andExpect(status().is(status.value())) - .andReturn(); + .andExpect(status().is(status.value())).andReturn(); } private boolean notSampledHeaderIsPresent(MvcResult mvcResult) { @@ -309,6 +321,7 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { @RestController public static class TestController { + @Autowired private Tracer tracer; @@ -339,17 +352,21 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { logger.info("future"); return CompletableFuture.completedFuture("ping"); } + } @Configuration static class ManagementServer { + @Bean @Primary ManagementServerProperties managementServerProperties() { ManagementServerProperties managementServerProperties = new ManagementServerProperties(); - managementServerProperties.getServlet().setContextPath("/additionalContextPath"); + managementServerProperties.getServlet() + .setContextPath("/additionalContextPath"); return managementServerProperties; } + } @Bean @@ -357,7 +374,8 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { return new ArrayListSpanReporter(); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } @@ -366,10 +384,12 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { Filter myFilter(Tracer tracer) { return new MyFilter(tracer); } + } + } -//tag::response_headers[] +// tag::response_headers[] @Component @Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1) class MyFilter extends GenericFilterBean { @@ -380,7 +400,8 @@ class MyFilter extends GenericFilterBean { this.tracer = tracer; } - @Override public void doFilter(ServletRequest request, ServletResponse response, + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Span currentSpan = this.tracer.currentSpan(); if (currentSpan == null) { @@ -388,12 +409,12 @@ class MyFilter extends GenericFilterBean { return; } // for readability we're returning trace id in a hex form - ((HttpServletResponse) response) - .addHeader("ZIPKIN-TRACE-ID", - currentSpan.context().traceIdString()); + ((HttpServletResponse) response).addHeader("ZIPKIN-TRACE-ID", + currentSpan.context().traceIdString()); // we can also add some custom tags currentSpan.tag("custom", "tag"); chain.doFilter(request, response); } + } -//end::response_headers[] \ No newline at end of file +// end::response_headers[] \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterTests.java index f258a34fa..6f882288f 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterTests.java @@ -60,24 +60,27 @@ public class TraceFilterTests { static final String SPAN_FLAGS = "X-B3-Flags"; ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + Tracer tracer = this.tracing.tracer(); + TraceKeys traceKeys = new TraceKeys(); + HttpTracing httpTracing = HttpTracing.newBuilder(this.tracing) .clientParser(new SleuthHttpClientParser(this.traceKeys)) - .serverParser(new SleuthHttpServerParser(this.traceKeys, - new ErrorParser())) - .serverSampler(new SleuthHttpSampler(() -> Pattern.compile(""))) - .build(); + .serverParser(new SleuthHttpServerParser(this.traceKeys, new ErrorParser())) + .serverSampler(new SleuthHttpSampler(() -> Pattern.compile(""))).build(); + Filter filter = TracingFilter.create(this.httpTracing); MockHttpServletRequest request; + MockHttpServletResponse response; + MockFilterChain filterChain; @Before @@ -112,87 +115,75 @@ public class TraceFilterTests { private Filter neverSampleFilter() { Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .sampler(Sampler.NEVER_SAMPLE) - .supportsJoin(false) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).sampler(Sampler.NEVER_SAMPLE) + .supportsJoin(false).build(); HttpTracing httpTracing = HttpTracing.newBuilder(tracing) .clientParser(new SleuthHttpClientParser(this.traceKeys)) - .serverParser(new SleuthHttpServerParser(this.traceKeys, - new ErrorParser())) - .serverSampler(new SleuthHttpSampler(() -> Pattern.compile(""))) - .build(); + .serverParser( + new SleuthHttpServerParser(this.traceKeys, new ErrorParser())) + .serverSampler(new SleuthHttpSampler(() -> Pattern.compile(""))).build(); return TracingFilter.create(httpTracing); } @Test public void startsNewTrace() throws Exception { filter.doFilter(this.request, this.response, this.filterChain); - - then(this.reporter.getSpans()) - .hasSize(1); + + then(this.reporter.getSpans()).hasSize(1); then(this.reporter.getSpans().get(0).tags()) .containsEntry("http.url", "http://localhost/?foo=bar") - .containsEntry("http.host", "localhost") - .containsEntry("http.path", "/") + .containsEntry("http.host", "localhost").containsEntry("http.path", "/") .containsEntry("http.method", HttpMethod.GET.toString()); - // we don't check for status_code anymore cause Brave doesn't support it oob - //.containsEntry("http.status_code", "200") + // we don't check for status_code anymore cause Brave doesn't support it oob + // .containsEntry("http.status_code", "200") } @Test - public void shouldNotStoreHttpStatusCodeWhenResponseCodeHasNotYetBeenSet() throws Exception { + public void shouldNotStoreHttpStatusCodeWhenResponseCodeHasNotYetBeenSet() + throws Exception { this.response.setStatus(0); filter.doFilter(this.request, this.response, this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); + then(this.reporter.getSpans()).hasSize(1); then(this.reporter.getSpans().get(0).tags()) .doesNotContainKey("http.status_code"); } @Test public void startsNewTraceWithParentIdInHeaders() throws Exception { - this.request = builder() - .header(SPAN_ID_NAME, PARENT_ID) + this.request = builder().header(SPAN_ID_NAME, PARENT_ID) .header(TRACE_ID_NAME, SpanUtil.idToHex(2L)) .header(PARENT_SPAN_ID_NAME, SpanUtil.idToHex(3L)) .buildRequest(new MockServletContext()); - + filter.doFilter(this.request, this.response, this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); + then(this.reporter.getSpans()).hasSize(1); then(this.reporter.getSpans().get(0).id()).isEqualTo(PARENT_ID); then(this.reporter.getSpans().get(0).tags()) .containsEntry("http.url", "http://localhost/?foo=bar") - .containsEntry("http.host", "localhost") - .containsEntry("http.path", "/") + .containsEntry("http.host", "localhost").containsEntry("http.path", "/") .containsEntry("http.method", HttpMethod.GET.toString()); } @Test public void continuesATraceWhenSpanNotSampled() throws Exception { AtomicReference span = new AtomicReference<>(); - this.request = builder() - .header(SPAN_ID_NAME, PARENT_ID) + this.request = builder().header(SPAN_ID_NAME, PARENT_ID) .header(TRACE_ID_NAME, SpanUtil.idToHex(2L)) .header(PARENT_SPAN_ID_NAME, SpanUtil.idToHex(3L)) - .header(SAMPLED_ID_NAME, 0) - .buildRequest(new MockServletContext()); - + .header(SAMPLED_ID_NAME, 0).buildRequest(new MockServletContext()); + filter.doFilter(this.request, this.response, (req, resp) -> { this.filterChain.doFilter(req, resp); span.set(this.tracing.tracer().currentSpan()); }); then(Tracing.current().tracer().currentSpan()).isNull(); - then(span.get().context().traceIdString()) - .isEqualTo(SpanUtil.idToHex(2L)); + then(span.get().context().traceIdString()).isEqualTo(SpanUtil.idToHex(2L)); } @Test @@ -212,12 +203,12 @@ public class TraceFilterTests { filter.doFilter(this.request, this.response, this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); + then(this.reporter.getSpans()).hasSize(1); } @Test - public void doesntDetachASpanIfStatusCodeNotSuccessfulAndRequestWasProcessed() throws Exception { + public void doesntDetachASpanIfStatusCodeNotSuccessfulAndRequestWasProcessed() + throws Exception { Span span = this.tracer.nextSpan().name("http:foo"); this.response.setStatus(404); @@ -241,23 +232,19 @@ public class TraceFilterTests { public void createsChildFromHeadersWhenJoinUnsupported() throws Exception { Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .supportsJoin(false) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).supportsJoin(false).build(); HttpTracing httpTracing = HttpTracing.create(tracing); this.request = builder().header(SPAN_ID_NAME, PARENT_ID) .header(TRACE_ID_NAME, SpanUtil.idToHex(20L)) .buildRequest(new MockServletContext()); - TracingFilter.create(httpTracing).doFilter(this.request, this.response, this.filterChain); + TracingFilter.create(httpTracing).doFilter(this.request, this.response, + this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); - then(this.reporter.getSpans().get(0).parentId()) - .isEqualTo(PARENT_ID); + then(this.reporter.getSpans()).hasSize(1); + then(this.reporter.getSpans().get(0).parentId()).isEqualTo(PARENT_ID); } @Test @@ -266,15 +253,13 @@ public class TraceFilterTests { .header(TRACE_ID_NAME, SpanUtil.idToHex(20L)) .buildRequest(new MockServletContext()); this.traceKeys.getHttp().getHeaders().add("x-foo"); - this.request.addHeader("X-Foo", "bar"); + this.request.addHeader("X-Foo", "bar"); filter.doFilter(this.request, this.response, this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); - then(this.reporter.getSpans().get(0).tags()) - .containsEntry("http.x-foo", "bar"); + then(this.reporter.getSpans()).hasSize(1); + then(this.reporter.getSpans().get(0).tags()).containsEntry("http.x-foo", "bar"); } @Test @@ -288,11 +273,9 @@ public class TraceFilterTests { filter.doFilter(this.request, this.response, this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); + then(this.reporter.getSpans()).hasSize(1); // We no longer support multi value headers - then(this.reporter.getSpans().get(0).tags()) - .containsEntry("http.x-foo", "bar"); + then(this.reporter.getSpans().get(0).tags()).containsEntry("http.x-foo", "bar"); } @Test @@ -305,7 +288,7 @@ public class TraceFilterTests { @Override public void doFilter(javax.servlet.ServletRequest request, javax.servlet.ServletResponse response) - throws java.io.IOException, javax.servlet.ServletException { + throws java.io.IOException, javax.servlet.ServletException { throw new RuntimeException("Planned"); } }; @@ -318,10 +301,8 @@ public class TraceFilterTests { then(Tracing.current().tracer().currentSpan()).isNull(); verifyParentSpanHttpTags(HttpStatus.INTERNAL_SERVER_ERROR); - then(this.reporter.getSpans()) - .hasSize(1); - then(this.reporter.getSpans().get(0).tags()) - .containsEntry("error", "Planned"); + then(this.reporter.getSpans()).hasSize(1); + then(this.reporter.getSpans().get(0).tags()).containsEntry("error", "Planned"); } @Test @@ -346,8 +327,7 @@ public class TraceFilterTests { filter.doFilter(this.request, this.response, this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); + then(this.reporter.getSpans()).hasSize(1); } @Test @@ -360,8 +340,7 @@ public class TraceFilterTests { filter.doFilter(this.request, this.response, this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); + then(this.reporter.getSpans()).hasSize(1); } @Test @@ -392,9 +371,9 @@ public class TraceFilterTests { } @Test - public void samplesASpanRegardlessOfTheSamplerWhenXB3FlagsIsPresentAndSetTo1() throws Exception { - this.request = builder() - .header(SPAN_FLAGS, 1) + public void samplesASpanRegardlessOfTheSamplerWhenXB3FlagsIsPresentAndSetTo1() + throws Exception { + this.request = builder().header(SPAN_FLAGS, 1) .buildRequest(new MockServletContext()); neverSampleFilter().doFilter(this.request, this.response, this.filterChain); @@ -404,9 +383,9 @@ public class TraceFilterTests { } @Test - public void doesNotOverrideTheSampledFlagWhenXB3FlagIsSetToOtherValueThan1() throws Exception { - this.request = builder() - .header(SPAN_FLAGS, 0) + public void doesNotOverrideTheSampledFlagWhenXB3FlagIsSetToOtherValueThan1() + throws Exception { + this.request = builder().header(SPAN_FLAGS, 0) .buildRequest(new MockServletContext()); filter.doFilter(this.request, this.response, this.filterChain); @@ -418,8 +397,7 @@ public class TraceFilterTests { @SuppressWarnings("Duplicates") @Test public void samplesWhenDebugFlagIsSetTo1AndOnlySpanIdIsSet() throws Exception { - this.request = builder() - .header(SPAN_FLAGS, 1) + this.request = builder().header(SPAN_FLAGS, 1) .header(SPAN_ID_NAME, SpanUtil.idToHex(10L)) .buildRequest(new MockServletContext()); @@ -427,16 +405,14 @@ public class TraceFilterTests { then(Tracing.current().tracer().currentSpan()).isNull(); // It is ok to go without a trace ID, if sampling or debug is set - then(this.reporter.getSpans()) - .hasSize(1) - .extracting("id").isNotEqualTo(SpanUtil.idToHex(10L)); + then(this.reporter.getSpans()).hasSize(1).extracting("id") + .isNotEqualTo(SpanUtil.idToHex(10L)); } @SuppressWarnings("Duplicates") @Test public void usesSamplingMechanismWhenIncomingTraceIsMalformed() throws Exception { - this.request = builder() - .header(SPAN_FLAGS, 1) + this.request = builder().header(SPAN_FLAGS, 1) .header(TRACE_ID_NAME, SpanUtil.idToHex(10L)) .buildRequest(new MockServletContext()); @@ -449,36 +425,31 @@ public class TraceFilterTests { // #668 @Test public void shouldSetTraceKeysForAnUntracedRequest() throws Exception { - this.request = builder() - .param("foo", "bar") + this.request = builder().param("foo", "bar") .buildRequest(new MockServletContext()); this.response.setStatus(295); filter.doFilter(this.request, this.response, this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); + then(this.reporter.getSpans()).hasSize(1); then(this.reporter.getSpans().get(0).tags()) .containsEntry("http.url", "http://localhost/?foo=bar") - .containsEntry("http.host", "localhost") - .containsEntry("http.path", "/") + .containsEntry("http.host", "localhost").containsEntry("http.path", "/") .containsEntry("http.method", HttpMethod.GET.toString()); - // we don't check for status_code anymore cause Brave doesn't support it oob - //.containsEntry("http.status_code", "295") + // we don't check for status_code anymore cause Brave doesn't support it oob + // .containsEntry("http.status_code", "295") } @Test public void samplesASpanDebugFlagWithInterceptor() throws Exception { - this.request = builder() - .header(SPAN_FLAGS, 1) + this.request = builder().header(SPAN_FLAGS, 1) .buildRequest(new MockServletContext()); neverSampleFilter().doFilter(this.request, this.response, this.filterChain); then(Tracing.current().tracer().currentSpan()).isNull(); - then(this.reporter.getSpans()) - .hasSize(1); + then(this.reporter.getSpans()).hasSize(1); then(this.reporter.getSpans().get(0).name()).isEqualTo("http:/"); } @@ -494,8 +465,7 @@ public class TraceFilterTests { then(this.reporter.getSpans().size()).isGreaterThan(0); then(this.reporter.getSpans().get(0).tags()) .containsEntry("http.url", "http://localhost/?foo=bar") - .containsEntry("http.host", "localhost") - .containsEntry("http.path", "/") + .containsEntry("http.host", "localhost").containsEntry("http.path", "/") .containsEntry("http.method", HttpMethod.GET.toString()); verifyCurrentSpanStatusCodeForAContinuedSpan(status); @@ -505,16 +475,15 @@ public class TraceFilterTests { // Status is only interesting in non-success case. Omitting it saves at least // 20bytes per span. if (status.is2xxSuccessful()) { - then(this.reporter.getSpans()) - .hasSize(1); + then(this.reporter.getSpans()).hasSize(1); then(this.reporter.getSpans().get(0).tags()) .doesNotContainKey("http.status_code"); } else { - then(this.reporter.getSpans()) - .hasSize(1); - then(this.reporter.getSpans().get(0).tags()) - .containsEntry("http.status_code", "500"); + then(this.reporter.getSpans()).hasSize(1); + then(this.reporter.getSpans().get(0).tags()).containsEntry("http.status_code", + "500"); } } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterWebIntegrationMultipleFiltersTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterWebIntegrationMultipleFiltersTests.java index 01c798ec4..6d6869fbf 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterWebIntegrationMultipleFiltersTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterWebIntegrationMultipleFiltersTests.java @@ -53,20 +53,36 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = { TraceFilterWebIntegrationMultipleFiltersTests.Config.class }, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = "spring.sleuth.http.legacy.enabled=true") +@SpringBootTest(classes = { + TraceFilterWebIntegrationMultipleFiltersTests.Config.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "spring.sleuth.http.legacy.enabled=true") public class TraceFilterWebIntegrationMultipleFiltersTests { - @Autowired Tracing tracer; - @Autowired RestTemplate restTemplate; - @Autowired Environment environment; - @Autowired MyFilter myFilter; - @Autowired ArrayListSpanReporter reporter; + @Autowired + Tracing tracer; + + @Autowired + RestTemplate restTemplate; + + @Autowired + Environment environment; + + @Autowired + MyFilter myFilter; + + @Autowired + ArrayListSpanReporter reporter; + // issue #550 - @Autowired @Qualifier("myExecutor") Executor myExecutor; - @Autowired @Qualifier("finalExecutor") Executor finalExecutor; - @Autowired MyExecutor cglibExecutor; + @Autowired + @Qualifier("myExecutor") + Executor myExecutor; + + @Autowired + @Qualifier("finalExecutor") + Executor finalExecutor; + + @Autowired + MyExecutor cglibExecutor; @Test public void should_register_trace_filter_before_the_custom_filter() { @@ -90,48 +106,57 @@ public class TraceFilterWebIntegrationMultipleFiltersTests { public static class Config { // issue #550 - @Bean Executor myExecutor() { + @Bean + Executor myExecutor() { return new MyExecutorWithFinalMethod(); } // issue #550 - @Bean MyExecutor cglibExecutor() { + @Bean + MyExecutor cglibExecutor() { return new MyExecutor(); } // issue #550 - @Bean MyFinalExecutor finalExecutor() { + @Bean + MyFinalExecutor finalExecutor() { return new MyFinalExecutor(); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean RestTemplate restTemplate() { + @Bean + RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { - @Override public void handleError(ClientHttpResponse response) - throws IOException { + @Override + public void handleError(ClientHttpResponse response) throws IOException { } }); return restTemplate; } - @Bean MyFilter myFilter(Tracing tracer) { + @Bean + MyFilter myFilter(Tracing tracer) { return new MyFilter(tracer); } - @Bean FilterRegistrationBean registrationBean(MyFilter myFilter) { + @Bean + FilterRegistrationBean registrationBean(MyFilter myFilter) { FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(myFilter); bean.setOrder(0); return bean; } - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } + } static class MyFilter extends GenericFilterBean { @@ -144,7 +169,8 @@ public class TraceFilterWebIntegrationMultipleFiltersTests { this.tracer = tracer; } - @Override public void doFilter(ServletRequest request, ServletResponse response, + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Span currentSpan = tracer.tracer().currentSpan(); this.span.set(currentSpan); @@ -153,13 +179,15 @@ public class TraceFilterWebIntegrationMultipleFiltersTests { public AtomicReference getSpan() { return span; } + } static class MyExecutor implements Executor { private final Executor delegate = Executors.newSingleThreadExecutor(); - @Override public void execute(Runnable command) { + @Override + public void execute(Runnable command) { this.delegate.execute(command); } @@ -167,13 +195,15 @@ public class TraceFilterWebIntegrationMultipleFiltersTests { public void destroy() { ((ExecutorService) this.delegate).shutdown(); } + } static class MyExecutorWithFinalMethod implements Executor { private final Executor delegate = Executors.newSingleThreadExecutor(); - @Override public final void execute(Runnable command) { + @Override + public final void execute(Runnable command) { this.delegate.execute(command); } @@ -181,13 +211,15 @@ public class TraceFilterWebIntegrationMultipleFiltersTests { public void destroy() { ((ExecutorService) this.delegate).shutdown(); } + } static final class MyFinalExecutor implements Executor { private final Executor delegate = Executors.newSingleThreadExecutor(); - @Override public void execute(Runnable command) { + @Override + public void execute(Runnable command) { this.delegate.execute(command); } @@ -195,5 +227,7 @@ public class TraceFilterWebIntegrationMultipleFiltersTests { public void destroy() { ((ExecutorService) this.delegate).shutdown(); } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterWebIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterWebIntegrationTests.java index b3970917c..0ef9292d0 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterWebIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterWebIntegrationTests.java @@ -58,16 +58,24 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = TraceFilterWebIntegrationTests.Config.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = "spring.sleuth.http.legacy.enabled=true") +@SpringBootTest(classes = TraceFilterWebIntegrationTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "spring.sleuth.http.legacy.enabled=true") public class TraceFilterWebIntegrationTests { - @Autowired Tracing tracer; - @Autowired ArrayListSpanReporter accumulator; - @Autowired @ServerSampler HttpSampler sampler; - @Autowired Environment environment; - @Rule public OutputCapture capture = new OutputCapture(); + @Autowired + Tracing tracer; + + @Autowired + ArrayListSpanReporter accumulator; + + @Autowired + @ServerSampler + HttpSampler sampler; + + @Autowired + Environment environment; + + @Rule + public OutputCapture capture = new OutputCapture(); @Before @After @@ -78,24 +86,26 @@ public class TraceFilterWebIntegrationTests { @Test public void should_not_create_a_span_for_error_controller() { try { - new RestTemplate().getForObject("http://localhost:" + port() + "/", String.class); + new RestTemplate().getForObject("http://localhost:" + port() + "/", + String.class); BDDAssertions.fail("should fail due to runtime exception"); - } catch (Exception e) { + } + catch (Exception e) { } then(Tracing.current().tracer().currentSpan()).isNull(); then(this.accumulator.getSpans()).hasSize(1); Span fromFirstTraceFilterFlow = this.accumulator.getSpans().get(0); - then(fromFirstTraceFilterFlow.tags()) - .containsEntry("http.status_code", "500") + then(fromFirstTraceFilterFlow.tags()).containsEntry("http.status_code", "500") .containsEntry("http.method", "GET") .containsEntry("mvc.controller.class", "ExceptionThrowingController") - .containsEntry("error", "Request processing failed; nested exception is java.lang.RuntimeException: Throwing exception"); + .containsEntry("error", + "Request processing failed; nested exception is java.lang.RuntimeException: Throwing exception"); // issue#714 String hex = fromFirstTraceFilterFlow.traceId(); String[] split = capture.toString().split("\n"); - List list = Arrays.stream(split).filter(s -> s.contains( - "Uncaught exception thrown")) + List list = Arrays.stream(split) + .filter(s -> s.contains("Uncaught exception thrown")) .filter(s -> s.contains(hex + "," + hex + ",true]")) .collect(Collectors.toList()); then(list).isNotEmpty(); @@ -104,16 +114,21 @@ public class TraceFilterWebIntegrationTests { @Test public void should_create_spans_for_endpoint_returning_unsuccessful_result() { try { - new RestTemplate().getForObject("http://localhost:" + port() + "/test_bad_request", String.class); + new RestTemplate().getForObject( + "http://localhost:" + port() + "/test_bad_request", String.class); fail("should throw exception"); - } catch (HttpClientErrorException e) { + } + catch (HttpClientErrorException e) { } then(Tracing.current().tracer().currentSpan()).isNull(); then(this.accumulator.getSpans()).hasSize(1); - then(this.accumulator.getSpans().get(0).kind().ordinal()).isEqualTo(Span.Kind.SERVER.ordinal()); - then(this.accumulator.getSpans().get(0).tags()).containsEntry("http.status_code", "400"); - then(this.accumulator.getSpans().get(0).tags()).containsEntry("http.path", "/test_bad_request"); + then(this.accumulator.getSpans().get(0).kind().ordinal()) + .isEqualTo(Span.Kind.SERVER.ordinal()); + then(this.accumulator.getSpans().get(0).tags()).containsEntry("http.status_code", + "400"); + then(this.accumulator.getSpans().get(0).tags()).containsEntry("http.path", + "/test_bad_request"); } @Test @@ -129,15 +144,18 @@ public class TraceFilterWebIntegrationTests { @Configuration public static class Config { - @Bean ExceptionThrowingController controller() { + @Bean + ExceptionThrowingController controller() { return new ExceptionThrowingController(); } - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } @@ -147,7 +165,8 @@ public class TraceFilterWebIntegrationTests { Pattern pattern = provider.skipPattern(); return new HttpSampler() { - @Override public Boolean trySample(HttpAdapter adapter, Req request) { + @Override + public Boolean trySample(HttpAdapter adapter, Req request) { String url = adapter.path(request); boolean shouldSkip = pattern.matcher(url).matches(); if (shouldSkip) { @@ -159,15 +178,17 @@ public class TraceFilterWebIntegrationTests { } // end::custom_server_sampler[] - @Bean RestTemplate restTemplate() { + @Bean + RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); restTemplate.setErrorHandler(new DefaultResponseErrorHandler() { - @Override public void handleError(ClientHttpResponse response) - throws IOException { + @Override + public void handleError(ClientHttpResponse response) throws IOException { } }); return restTemplate; } + } @RestController @@ -182,5 +203,7 @@ public class TraceFilterWebIntegrationTests { public ResponseEntity processFail() { return ResponseEntity.badRequest().build(); } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceNoWebEnvironmentTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceNoWebEnvironmentTests.java index cfbddc87f..15bc56588 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceNoWebEnvironmentTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceNoWebEnvironmentTests.java @@ -47,7 +47,8 @@ public class TraceNoWebEnvironmentTests { client.createSomeTestRequest(); } catch (Exception e) { - then(e.getCause().getClass()).isNotEqualTo(NoSuchBeanDefinitionException.class); + then(e.getCause().getClass()) + .isNotEqualTo(NoSuchBeanDefinitionException.class); } } @@ -55,7 +56,7 @@ public class TraceNoWebEnvironmentTests { @EnableAutoConfiguration @EnableFeignClients(clients = Config.SomeFeignClient.class) @EnableCircuitBreaker - public static class Config { + public static class Config { @FeignClient(name = "google", url = "https://www.google.com/") public interface SomeFeignClient { @@ -64,5 +65,7 @@ public class TraceNoWebEnvironmentTests { String createSomeTestRequest(); } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceRestTemplateInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceRestTemplateInterceptorTests.java index 9bb53042e..457715ef5 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceRestTemplateInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceRestTemplateInterceptorTests.java @@ -55,18 +55,22 @@ import static org.assertj.core.api.BDDAssertions.then; public class TraceRestTemplateInterceptorTests { private TestController testController = new TestController(); + private MockMvc mockMvc = MockMvcBuilders.standaloneSetup(this.testController) .build(); + private RestTemplate template = new RestTemplate( new MockMvcClientHttpRequestFactory(this.mockMvc)); + ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + Tracer tracer = this.tracing.tracer(); + TraceKeys traceKeys = new TraceKeys(); @Before @@ -99,62 +103,57 @@ public class TraceRestTemplateInterceptorTests { Span span = this.tracer.nextSpan().name("new trace"); Map headers; - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { - headers = this.template.getForEntity("/", Map.class) - .getBody(); - } finally { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + headers = this.template.getForEntity("/", Map.class).getBody(); + } + finally { span.finish(); } - then(headers.get("X-B3-TraceId")).isEqualTo( - SpanUtil.idToHex(span.context().traceId())); - then(headers.get("X-B3-SpanId")).isNotEqualTo( - SpanUtil.idToHex(span.context().spanId())); - then(headers.get("X-B3-ParentSpanId")).isEqualTo( - SpanUtil.idToHex(span.context().spanId())); + then(headers.get("X-B3-TraceId")) + .isEqualTo(SpanUtil.idToHex(span.context().traceId())); + then(headers.get("X-B3-SpanId")) + .isNotEqualTo(SpanUtil.idToHex(span.context().spanId())); + then(headers.get("X-B3-ParentSpanId")) + .isEqualTo(SpanUtil.idToHex(span.context().spanId())); } // Issue #290 @Test public void requestHeadersAddedWhenTracing() { setInterceptors(HttpTracing.newBuilder(this.tracing) - .clientParser(new SleuthHttpClientParser(this.traceKeys)) - .build()); + .clientParser(new SleuthHttpClientParser(this.traceKeys)).build()); Span span = this.tracer.nextSpan().name("new trace"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { this.template.getForEntity("/foo?a=b", Map.class); - } finally { + } + finally { span.finish(); } List spans = reporter.getSpans(); then(spans).isNotEmpty(); - then(spans.get(0).tags()) - .containsEntry("http.url", "/foo?a=b") - .containsEntry("http.path", "/foo") - .containsEntry("http.method", "GET"); + then(spans.get(0).tags()).containsEntry("http.url", "/foo?a=b") + .containsEntry("http.path", "/foo").containsEntry("http.method", "GET"); } @Test public void notSampledHeaderAddedWhenNotExportable() { Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .sampler(Sampler.NEVER_SAMPLE) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).sampler(Sampler.NEVER_SAMPLE).build(); this.template.setInterceptors(Arrays.asList( TracingClientHttpRequestInterceptor.create(HttpTracing.create(tracing)))); Span span = tracing.tracer().nextSpan().name("new trace"); Map headers; - try(Tracer.SpanInScope ws = tracing.tracer().withSpanInScope(span.start())) { - headers = this.template.getForEntity("/", Map.class) - .getBody(); - } finally { + try (Tracer.SpanInScope ws = tracing.tracer().withSpanInScope(span.start())) { + headers = this.template.getForEntity("/", Map.class).getBody(); + } + finally { span.finish(); } @@ -166,12 +165,14 @@ public class TraceRestTemplateInterceptorTests { public void spanRemovedFromThreadUponException() { Span span = this.tracer.nextSpan().name("new trace"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { this.template.getForEntity("/exception", Map.class).getBody(); Assert.fail("should throw an exception"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { then(e).hasMessage("500 Internal Server Error"); - } finally { + } + finally { span.finish(); } @@ -181,46 +182,46 @@ public class TraceRestTemplateInterceptorTests { @Test public void createdSpanNameHasOnlyPrintableAsciiCharactersForNonEncodedURIWithNonAsciiChars() { setInterceptors(HttpTracing.newBuilder(this.tracing) - .clientParser(new SleuthHttpClientParser(this.traceKeys)) - .build()); + .clientParser(new SleuthHttpClientParser(this.traceKeys)).build()); Span span = this.tracer.nextSpan().name("new trace"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { this.template.getForEntity("/cas~fs~划", Map.class).getBody(); - } catch (Exception e) { + } + catch (Exception e) { - } finally { + } + finally { span.finish(); } List spans = reporter.getSpans(); then(spans).hasSize(2); String spanName = spans.get(0).name(); - then(spanName) - .isEqualTo("http:/cas~fs~%c3%a5%cb%86%e2%80%99"); + then(spanName).isEqualTo("http:/cas~fs~%c3%a5%cb%86%e2%80%99"); then(StringUtils.isAsciiPrintable(spanName)); } @Test public void willShortenTheNameOfTheSpan() { setInterceptors(HttpTracing.newBuilder(this.tracing) - .clientParser(new SleuthHttpClientParser(this.traceKeys)) - .build()); + .clientParser(new SleuthHttpClientParser(this.traceKeys)).build()); Span span = this.tracer.nextSpan().name("new trace"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { this.template.getForEntity("/" + bigName(), Map.class).getBody(); - } catch (Exception e) { + } + catch (Exception e) { - } finally { + } + finally { span.finish(); } List spans = reporter.getSpans(); then(spans).isNotEmpty(); String spanName = spans.get(0).name(); - then(spanName) - .hasSize(50); + then(spanName).hasSize(50); then(StringUtils.isAsciiPrintable(spanName)); } @@ -241,8 +242,7 @@ public class TraceRestTemplateInterceptorTests { public Map home(@RequestHeader HttpHeaders headers) { this.span = TraceRestTemplateInterceptorTests.this.tracer.currentSpan(); Map map = new HashMap(); - addHeaders(map, headers, "X-B3-SpanId", "X-B3-TraceId", - "X-B3-ParentSpanId"); + addHeaders(map, headers, "X-B3-SpanId", "X-B3-TraceId", "X-B3-ParentSpanId"); return map; } @@ -266,7 +266,7 @@ public class TraceRestTemplateInterceptorTests { } } } + } } - diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebDisabledTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebDisabledTests.java index 0d1ebbf1a..91d7e3c75 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebDisabledTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebDisabledTests.java @@ -39,5 +39,7 @@ public class TraceWebDisabledTests { @Configuration @EnableAutoConfiguration public static class Config { + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFluxTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFluxTests.java index a634cc992..3cab94719 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFluxTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebFluxTests.java @@ -59,21 +59,27 @@ public class TraceWebFluxTests { Schedulers.resetFactory(); } - @Test public void should_instrument_web_filter() throws Exception { + @Test + public void should_instrument_web_filter() throws Exception { // setup ConfigurableApplicationContext context = new SpringApplicationBuilder( - TraceWebFluxTests.Config.class).web(WebApplicationType.REACTIVE) - .properties("server.port=0", "spring.jmx.enabled=false", "spring.sleuth.web.skipPattern=/skipped", - "spring.application.name=TraceWebFluxTests", "security.basic.enabled=false", - "management.security.enabled=false").run(); + TraceWebFluxTests.Config.class) + .web(WebApplicationType.REACTIVE) + .properties("server.port=0", "spring.jmx.enabled=false", + "spring.sleuth.web.skipPattern=/skipped", + "spring.application.name=TraceWebFluxTests", + "security.basic.enabled=false", + "management.security.enabled=false") + .run(); ArrayListSpanReporter accumulator = context.getBean(ArrayListSpanReporter.class); - int port = context.getBean(Environment.class).getProperty("local.server.port", Integer.class); + int port = context.getBean(Environment.class).getProperty("local.server.port", + Integer.class); Controller2 controller2 = context.getBean(Controller2.class); clean(accumulator, controller2); // when ClientResponse response = whenRequestIsSent(port); - //then + // then thenSpanWasReportedWithTags(accumulator, response); clean(accumulator, controller2); @@ -155,8 +161,7 @@ public class TraceWebFluxTests { Mono exchange = WebClient.create().get() .uri("http://localhost:" + port + "/api/c2/10") .header("X-B3-SpanId", EXPECTED_TRACE_ID) - .header("X-B3-TraceId", EXPECTED_TRACE_ID) - .header("X-B3-Sampled", "0") + .header("X-B3-TraceId", EXPECTED_TRACE_ID).header("X-B3-Sampled", "0") .exchange(); return exchange.block(); } @@ -166,28 +171,34 @@ public class TraceWebFluxTests { @DisableWebFluxSecurity static class Config { - @Bean WebClient webClient() { + @Bean + WebClient webClient() { return WebClient.create(); } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean ArrayListSpanReporter spanReporter() { + @Bean + ArrayListSpanReporter spanReporter() { return new ArrayListSpanReporter(); } - @Bean Controller2 controller2(Tracer tracer) { + @Bean + Controller2 controller2(Tracer tracer) { return new Controller2(tracer); } - @Bean RouterFunction function() { + @Bean + RouterFunction function() { return RouterFunctions.route(RequestPredicates.GET("/function"), r -> { then(MDC.get("X-B3-TraceId")).isNotEmpty(); return ServerResponse.ok().syncBody("functionOk"); }); } + } @RestController @@ -215,6 +226,7 @@ public class TraceWebFluxTests { then(sampled).isFalse(); return Flux.just(sampled.toString()); } - } -} + } + +} diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java index 794b2031a..4bc50114d 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java @@ -31,47 +31,53 @@ import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.client.RestTemplate; -@SpringBootTest(classes = GH846Test.App.class, webEnvironment=WebEnvironment.NONE) +@SpringBootTest(classes = GH846Test.App.class, webEnvironment = WebEnvironment.NONE) @RunWith(SpringRunner.class) public class GH846Test { @Autowired private MyBean myBean; - + @Test public void doit() throws Exception { int count = myBean.listAndCount(); - Assert.assertEquals("Change detected in RestTemplate interceptor *after* @PostConstruct", count, myBean.getCountAtPostConstruct()); + Assert.assertEquals( + "Change detected in RestTemplate interceptor *after* @PostConstruct", + count, myBean.getCountAtPostConstruct()); } - + @EnableAutoConfiguration @Configuration static class App { + @Bean public RestTemplate myRestTemplate() { return new RestTemplate(); } - + @Bean public MyBean myBean() { return new MyBean(); } + } static class MyBean { + @Autowired private RestTemplate restTemplate; - - /** Number of interceptors registered in the RestTemplate during @PostConstruct */ + + /** Number of interceptors registered in the RestTemplate during @PostConstruct */ private int countAtPostConstruct; - + @PostConstruct public void init() { countAtPostConstruct = listAndCount(); } - + public int listAndCount() { - for(ClientHttpRequestInterceptor interceptor: restTemplate.getInterceptors()) { + for (ClientHttpRequestInterceptor interceptor : restTemplate + .getInterceptors()) { System.out.println(interceptor); } return restTemplate.getInterceptors().size(); @@ -80,5 +86,7 @@ public class GH846Test { public int getCountAtPostConstruct() { return countAtPostConstruct; } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/MultipleAsyncRestTemplateTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/MultipleAsyncRestTemplateTests.java index 54d1429b2..44d53234f 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/MultipleAsyncRestTemplateTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/MultipleAsyncRestTemplateTests.java @@ -63,21 +63,29 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest( - classes = { MultipleAsyncRestTemplateTests.Config.class, - MultipleAsyncRestTemplateTests.CustomExecutorConfig.class, - MultipleAsyncRestTemplateTests.ControllerConfig.class }, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@SpringBootTest(classes = { MultipleAsyncRestTemplateTests.Config.class, + MultipleAsyncRestTemplateTests.CustomExecutorConfig.class, + MultipleAsyncRestTemplateTests.ControllerConfig.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @DirtiesContext public class MultipleAsyncRestTemplateTests { - private static final Log log = LogFactory.getLog(MultipleAsyncRestTemplateTests.class); + private static final Log log = LogFactory + .getLog(MultipleAsyncRestTemplateTests.class); + + @Autowired + @Qualifier("customAsyncRestTemplate") + AsyncRestTemplate asyncRestTemplate; + + @Autowired + AsyncConfigurer executor; - @Autowired @Qualifier("customAsyncRestTemplate") AsyncRestTemplate asyncRestTemplate; - @Autowired AsyncConfigurer executor; Executor wrappedExecutor; - @Autowired Tracer tracer; - @LocalServerPort int port; + + @Autowired + Tracer tracer; + + @LocalServerPort + int port; @Before public void setup() { @@ -93,10 +101,12 @@ public class MultipleAsyncRestTemplateTests { public void should_pass_tracing_context_with_custom_async_client() throws Exception { Span span = this.tracer.nextSpan().name("foo"); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { - String result = this.asyncRestTemplate.getForEntity("http://localhost:" - + port + "/foo", String.class).get().getBody(); + String result = this.asyncRestTemplate + .getForEntity("http://localhost:" + port + "/foo", String.class).get() + .getBody(); then(span.context().traceIdString()).isEqualTo(result); - } finally { + } + finally { span.finish(); } @@ -112,7 +122,8 @@ public class MultipleAsyncRestTemplateTests { } @Test - public void should_inject_traced_executor_that_passes_tracing_context() throws Exception { + public void should_inject_traced_executor_that_passes_tracing_context() + throws Exception { Span span = this.tracer.nextSpan().name("foo"); AtomicBoolean executed = new AtomicBoolean(false); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { @@ -122,55 +133,60 @@ public class MultipleAsyncRestTemplateTests { then(currentSpan).isNotNull(); long currentTraceId = currentSpan.context().traceId(); long initialTraceId = span.context().traceId(); - log.info("Hello from runnable before trace id check. Initial [" + initialTraceId + "] current [" + currentTraceId + "]"); + log.info("Hello from runnable before trace id check. Initial [" + + initialTraceId + "] current [" + currentTraceId + "]"); then(currentTraceId).isEqualTo(initialTraceId); executed.set(true); log.info("Hello from runnable"); }); - } finally { + } + finally { span.finish(); } - Awaitility.await().atMost(10L, TimeUnit.SECONDS) - .untilAsserted(() -> { - then(executed.get()).isTrue(); - }); + Awaitility.await().atMost(10L, TimeUnit.SECONDS).untilAsserted(() -> { + then(executed.get()).isTrue(); + }); then(this.tracer.currentSpan()).isNull(); } - //tag::custom_async_rest_template[] + // tag::custom_async_rest_template[] @Configuration @EnableAutoConfiguration static class Config { @Bean(name = "customAsyncRestTemplate") public AsyncRestTemplate traceAsyncRestTemplate() { - return new AsyncRestTemplate(asyncClientFactory(), clientHttpRequestFactory()); + return new AsyncRestTemplate(asyncClientFactory(), + clientHttpRequestFactory()); } private ClientHttpRequestFactory clientHttpRequestFactory() { ClientHttpRequestFactory clientHttpRequestFactory = new CustomClientHttpRequestFactory(); - //CUSTOMIZE HERE + // CUSTOMIZE HERE return clientHttpRequestFactory; } private AsyncClientHttpRequestFactory asyncClientFactory() { AsyncClientHttpRequestFactory factory = new CustomAsyncClientHttpRequestFactory(); - //CUSTOMIZE HERE + // CUSTOMIZE HERE return factory; } - } - //end::custom_async_rest_template[] - //tag::custom_executor[] + } + // end::custom_async_rest_template[] + + // tag::custom_executor[] @Configuration @EnableAutoConfiguration @EnableAsync static class CustomExecutorConfig extends AsyncConfigurerSupport { - @Autowired BeanFactory beanFactory; + @Autowired + BeanFactory beanFactory; - @Override public Executor getAsyncExecutor() { + @Override + public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // CUSTOMIZE HERE executor.setCorePoolSize(7); @@ -181,30 +197,37 @@ public class MultipleAsyncRestTemplateTests { executor.initialize(); return new LazyTraceExecutor(this.beanFactory, executor); } + } - //end::custom_executor[] + // end::custom_executor[] @Configuration static class ControllerConfig { + @Bean MyRestController myRestController(Tracer tracer) { return new MyRestController(tracer); } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } + } + } class CustomClientHttpRequestFactory implements ClientHttpRequestFactory { private final SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); - @Override public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) + @Override + public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { return this.factory.createRequest(uri, httpMethod); } + } class CustomAsyncClientHttpRequestFactory implements AsyncClientHttpRequestFactory { @@ -220,6 +243,7 @@ class CustomAsyncClientHttpRequestFactory implements AsyncClientHttpRequestFacto throws IOException { return this.factory.createAsyncRequest(uri, httpMethod); } + } @RestController @@ -235,4 +259,5 @@ class MyRestController { String foo() { return this.tracer.currentSpan().context().traceIdString(); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/RestTemplateTraceAspectIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/RestTemplateTraceAspectIntegrationTests.java index 2a43df03e..77c4b6266 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/RestTemplateTraceAspectIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/RestTemplateTraceAspectIntegrationTests.java @@ -61,31 +61,42 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = RestTemplateTraceAspectIntegrationTests.Config.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = "spring.sleuth.web.client.skipPattern=/issue.*") +@SpringBootTest(classes = RestTemplateTraceAspectIntegrationTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "spring.sleuth.web.client.skipPattern=/issue.*") @DirtiesContext public class RestTemplateTraceAspectIntegrationTests { - @Autowired WebApplicationContext context; - @Autowired AspectTestingController controller; - @Autowired Tracing tracer; - @Autowired ArrayListSpanReporter reporter; - @Autowired RestTemplate restTemplate; + @Autowired + WebApplicationContext context; + + @Autowired + AspectTestingController controller; + + @Autowired + Tracing tracer; + + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + RestTemplate restTemplate; private MockMvc mockMvc; - @Before public void init() { + @Before + public void init() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); this.controller.reset(); this.reporter.clear(); } - @Before @After public void verify() { + @Before + @After + public void verify() { then(this.tracer.tracer().currentSpan()).isNull(); } - @Test public void should_set_span_data_on_headers_via_aspect_in_synchronous_call() + @Test + public void should_set_span_data_on_headers_via_aspect_in_synchronous_call() throws Exception { whenARequestIsSentToASyncEndpoint(); @@ -141,10 +152,10 @@ public class RestTemplateTraceAspectIntegrationTests { .andReturn(); } - private void whenARequestIsSentToASyncEndpointThatShouldBeFilteredOut() throws Exception { - this.mockMvc.perform( - MockMvcRequestBuilders.get("/issue1047_start").accept(MediaType.TEXT_PLAIN)) - .andReturn(); + private void whenARequestIsSentToASyncEndpointThatShouldBeFilteredOut() + throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.get("/issue1047_start") + .accept(MediaType.TEXT_PLAIN)).andReturn(); } private void thenTraceIdHasBeenSetOnARequestHeader() { @@ -155,8 +166,7 @@ public class RestTemplateTraceAspectIntegrationTests { // that's why we have to pick only CLIENT side private void thenClientKindIsReported() { assertThat(this.reporter.getSpans().stream().map(Span::kind) - .collect(Collectors.toList())) - .contains(Span.Kind.CLIENT); + .collect(Collectors.toList())).contains(Span.Kind.CLIENT); } private void whenARequestIsSentToAnAsyncEndpoint(String url) throws Exception { @@ -171,95 +181,111 @@ public class RestTemplateTraceAspectIntegrationTests { @DefaultTestAutoConfiguration @Import(AspectTestingController.class) public static class Config { - @Bean public RestTemplate restTemplate() { + + @Bean + public RestTemplate restTemplate() { return new RestTemplate(); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean public AsyncRestTemplate asyncRestTemplate(Tracing tracing) { + @Bean + public AsyncRestTemplate asyncRestTemplate(Tracing tracing) { AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(); asyncRestTemplate.setInterceptors(Collections.singletonList( TracingAsyncClientHttpRequestInterceptor.create(tracing))); return asyncRestTemplate; } - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } + } - @RestController public static class AspectTestingController { + @RestController + public static class AspectTestingController { + + @Autowired + Tracing tracer; + + @Autowired + RestTemplate restTemplate; + + @Autowired + Environment environment; + + @Autowired + AsyncRestTemplate asyncRestTemplate; - @Autowired Tracing tracer; - @Autowired RestTemplate restTemplate; - @Autowired Environment environment; - @Autowired AsyncRestTemplate asyncRestTemplate; private String traceId; public void reset() { this.traceId = null; } - @RequestMapping(value = "/issue1047_end", method = RequestMethod.GET, - produces = MediaType.TEXT_PLAIN_VALUE) public String issue1047() { + @RequestMapping(value = "/issue1047_end", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) + public String issue1047() { return "should_filter_out_this_endpoint"; } - @RequestMapping(value = "/issue1047_start", method = RequestMethod.GET, - produces = MediaType.TEXT_PLAIN_VALUE) public String issue1047Start() { + @RequestMapping(value = "/issue1047_start", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) + public String issue1047Start() { return callAndReturnIssue1047(); } - @RequestMapping(value = "/", method = RequestMethod.GET, - produces = MediaType.TEXT_PLAIN_VALUE) public String home( + @RequestMapping(value = "/", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) + public String home( @RequestHeader(value = "X-B3-SpanId", required = false) String traceId) { this.traceId = traceId == null ? "UNKNOWN" : traceId; return "trace=" + this.getTraceId(); } - @RequestMapping(value = "/customTag", method = RequestMethod.GET, - produces = MediaType.TEXT_PLAIN_VALUE) public String customTag( + @RequestMapping(value = "/customTag", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) + public String customTag( @RequestHeader(value = "X-B3-TraceId", required = false) String traceId) { this.traceId = traceId == null ? "UNKNOWN" : traceId; return "trace=" + this.getTraceId(); } - @RequestMapping(value = "/asyncRestTemplate", method = RequestMethod.GET, - produces = MediaType.TEXT_PLAIN_VALUE) public String asyncRestTemplate() + @RequestMapping(value = "/asyncRestTemplate", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) + public String asyncRestTemplate() throws ExecutionException, InterruptedException { return callViaAsyncRestTemplateAndReturnOk(); } - @RequestMapping(value = "/syncPing", method = RequestMethod.GET, - produces = MediaType.TEXT_PLAIN_VALUE) public String syncPing() { + @RequestMapping(value = "/syncPing", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) + public String syncPing() { return callAndReturnOk(); } - @RequestMapping(value = "/callablePing", method = RequestMethod.GET, - produces = MediaType.TEXT_PLAIN_VALUE) + @RequestMapping(value = "/callablePing", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) public Callable asyncPing() { return new Callable() { - @Override public String call() throws Exception { + @Override + public String call() throws Exception { return callAndReturnOk(); } }; } - @RequestMapping(value = "/webAsyncTaskPing", method = RequestMethod.GET, - produces = MediaType.TEXT_PLAIN_VALUE) + @RequestMapping(value = "/webAsyncTaskPing", method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) public WebAsyncTask webAsyncTaskPing() { return new WebAsyncTask<>(new Callable() { - @Override public String call() throws Exception { + @Override + public String call() throws Exception { return callAndReturnOk(); } }); } private String callAndReturnIssue1047() { - this.restTemplate.getForObject("http://localhost:" + port() + "/issue1047_end", String.class); + this.restTemplate.getForObject( + "http://localhost:" + port() + "/issue1047_end", String.class); return "OK"; } @@ -282,5 +308,7 @@ public class RestTemplateTraceAspectIntegrationTests { String getTraceId() { return this.traceId; } + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorIntegrationTests.java index 7ef1e60e1..283f12be3 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorIntegrationTests.java @@ -48,23 +48,25 @@ import okhttp3.mockwebserver.SocketPolicy; */ public class TraceRestTemplateInterceptorIntegrationTests { - @Rule public final MockWebServer mockWebServer = new MockWebServer(); + @Rule + public final MockWebServer mockWebServer = new MockWebServer(); private RestTemplate template = new RestTemplate(clientHttpRequestFactory()); ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + Tracer tracer = this.tracing.tracer(); @Before public void setup() { - this.template.setInterceptors(Arrays.asList( - TracingClientHttpRequestInterceptor.create(HttpTracing.create(this.tracing)))); + this.template.setInterceptors(Arrays + .asList(TracingClientHttpRequestInterceptor + .create(HttpTracing.create(this.tracing)))); } @After @@ -75,25 +77,27 @@ public class TraceRestTemplateInterceptorIntegrationTests { // Issue #198 @Test public void spanRemovedFromThreadUponException() throws IOException { - this.mockWebServer.enqueue(new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AT_START)); + this.mockWebServer.enqueue( + new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AT_START)); Span span = this.tracer.nextSpan().name("new trace"); - try(Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { + try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { this.template.getForEntity( "http://localhost:" + this.mockWebServer.getPort() + "/exception", Map.class).getBody(); Assert.fail("should throw an exception"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { BDDAssertions.then(e).hasRootCauseInstanceOf(IOException.class); - } finally { + } + finally { span.finish(); } // 1 span "new race", 1 span "rest template" BDDAssertions.then(this.reporter.getSpans()).hasSize(2); zipkin2.Span span1 = this.reporter.getSpans().get(0); - BDDAssertions.then(span1.tags()) - .containsEntry("error", "Read timed out"); + BDDAssertions.then(span1.tags()).containsEntry("error", "Read timed out"); BDDAssertions.then(span1.kind().ordinal()).isEqualTo(Span.Kind.CLIENT.ordinal()); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfigurationTests.java index 8cbf78e83..11126eb2c 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfigurationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfigurationTests.java @@ -52,13 +52,20 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = { - TraceWebAsyncClientAutoConfigurationTests.TestConfiguration.class }, - webEnvironment = RANDOM_PORT) + TraceWebAsyncClientAutoConfigurationTests.TestConfiguration.class }, webEnvironment = RANDOM_PORT) public class TraceWebAsyncClientAutoConfigurationTests { - @Autowired AsyncRestTemplate asyncRestTemplate; - @Autowired Environment environment; - @Autowired ArrayListSpanReporter accumulator; - @Autowired Tracing tracer; + + @Autowired + AsyncRestTemplate asyncRestTemplate; + + @Autowired + Environment environment; + + @Autowired + ArrayListSpanReporter accumulator; + + @Autowired + Tracing tracer; @Before public void setup() { @@ -70,19 +77,22 @@ public class TraceWebAsyncClientAutoConfigurationTests { throws ExecutionException, InterruptedException { brave.Span initialSpan = this.tracer.tracer().nextSpan().name("foo"); - try (Tracer.SpanInScope ws = this.tracer.tracer().withSpanInScope(initialSpan.start())) { + try (Tracer.SpanInScope ws = this.tracer.tracer() + .withSpanInScope(initialSpan.start())) { ListenableFuture> future = this.asyncRestTemplate .getForEntity("http://localhost:" + port() + "/foo", String.class); String result = future.get().getBody(); then(result).isEqualTo("foo"); - } finally { + } + finally { initialSpan.finish(); } - then(this.accumulator.getSpans().stream() - .filter(span -> Span.Kind.CLIENT == span.kind()).findFirst().get()) - .matches(span -> span.duration() >= TimeUnit.MILLISECONDS.toMicros(100)); + then(this.accumulator + .getSpans().stream().filter(span -> Span.Kind.CLIENT == span.kind()) + .findFirst().get()).matches( + span -> span.duration() >= TimeUnit.MILLISECONDS.toMicros(100)); then(this.tracer.tracer().currentSpan()).isNull(); } @@ -91,11 +101,12 @@ public class TraceWebAsyncClientAutoConfigurationTests { throws ExecutionException, InterruptedException { ListenableFuture> future; try { - future = this.asyncRestTemplate - .getForEntity("http://localhost:" + port() + "/blowsup", String.class); + future = this.asyncRestTemplate.getForEntity( + "http://localhost:" + port() + "/blowsup", String.class); future.get(); BDDAssertions.fail("should throw an exception from the controller"); - } catch (Exception e) { + } + catch (Exception e) { } Awaitility.await().untilAsserted(() -> { @@ -113,14 +124,15 @@ public class TraceWebAsyncClientAutoConfigurationTests { } @EnableAutoConfiguration( - // spring boot test will otherwise instrument the client and server with the same bean factory + // spring boot test will otherwise instrument the client and server with the + // same bean factory // which isn't expected - exclude = TraceWebServletAutoConfiguration.class - ) + exclude = TraceWebServletAutoConfiguration.class) @Configuration public static class TestConfiguration { - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } @@ -129,7 +141,8 @@ public class TraceWebAsyncClientAutoConfigurationTests { return new MyController(); } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } @@ -137,6 +150,7 @@ public class TraceWebAsyncClientAutoConfigurationTests { AsyncRestTemplate restTemplate() { return new AsyncRestTemplate(); } + } @RestController @@ -153,6 +167,7 @@ public class TraceWebAsyncClientAutoConfigurationTests { Thread.sleep(100); throw new RuntimeException("boom"); } + } } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfigurationTests.java index 33f77c18c..6d6bc4674 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfigurationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfigurationTests.java @@ -47,21 +47,28 @@ import static org.assertj.core.api.BDDAssertions.then; @SpringBootTest(classes = TraceWebClientAutoConfigurationTests.Config.class) public class TraceWebClientAutoConfigurationTests { - @Autowired @Qualifier("firstRestTemplate") RestTemplate restTemplate; - @Autowired @Qualifier("secondRestTemplate") RestTemplate secondRestTemplate; - @Autowired RestTemplateBuilder builder; + @Autowired + @Qualifier("firstRestTemplate") + RestTemplate restTemplate; + + @Autowired + @Qualifier("secondRestTemplate") + RestTemplate secondRestTemplate; + + @Autowired + RestTemplateBuilder builder; @Test public void should_add_rest_template_interceptors() { - assertInterceptorsOrder(assertInterceptorsNotEmpty(this.restTemplate)); + assertInterceptorsOrder(assertInterceptorsNotEmpty(this.restTemplate)); assertInterceptorsOrder(assertInterceptorsNotEmpty(this.secondRestTemplate)); assertInterceptorsOrder(assertInterceptorsNotEmpty(this.builder.build())); } - private List assertInterceptorsNotEmpty(RestTemplate restTemplate) { + private List assertInterceptorsNotEmpty( + RestTemplate restTemplate) { then(restTemplate).isNotNull(); - List interceptors = restTemplate - .getInterceptors(); + List interceptors = restTemplate.getInterceptors(); then(interceptors).isNotEmpty(); return interceptors; } @@ -72,21 +79,20 @@ public class TraceWebClientAutoConfigurationTests { int myInterceptorIndex = -1; int mySecondInterceptorIndex = -1; for (int i = 0; i < interceptors.size(); i++) { - ClientHttpRequestInterceptor interceptor = interceptors - .get(i); - if (interceptor instanceof TracingClientHttpRequestInterceptor || - interceptor instanceof LazyTracingClientHttpRequestInterceptor) { + ClientHttpRequestInterceptor interceptor = interceptors.get(i); + if (interceptor instanceof TracingClientHttpRequestInterceptor + || interceptor instanceof LazyTracingClientHttpRequestInterceptor) { traceInterceptorIndex = i; - } else if (interceptor instanceof MyClientHttpRequestInterceptor) { + } + else if (interceptor instanceof MyClientHttpRequestInterceptor) { myInterceptorIndex = i; - } else if (interceptor instanceof MySecondClientHttpRequestInterceptor) { + } + else if (interceptor instanceof MySecondClientHttpRequestInterceptor) { mySecondInterceptorIndex = i; } } - then(traceInterceptorIndex) - .isGreaterThanOrEqualTo(0) - .isLessThan(myInterceptorIndex) - .isLessThan(mySecondInterceptorIndex); + then(traceInterceptorIndex).isGreaterThanOrEqualTo(0) + .isLessThan(myInterceptorIndex).isLessThan(mySecondInterceptorIndex); } @Configuration @@ -95,9 +101,9 @@ public class TraceWebClientAutoConfigurationTests { // custom builder @Bean - RestTemplateBuilder myRestTemplateBuilder(List customizers) { - return new RestTemplateBuilder() - .additionalCustomizers(customizers) + RestTemplateBuilder myRestTemplateBuilder( + List customizers) { + return new RestTemplateBuilder().additionalCustomizers(customizers) .additionalInterceptors(new MyClientHttpRequestInterceptor()); } @@ -105,8 +111,7 @@ public class TraceWebClientAutoConfigurationTests { @Bean @Qualifier("firstRestTemplate") RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { - return restTemplateBuilder - .build(); + return restTemplateBuilder.build(); } // manual rest template @@ -114,8 +119,8 @@ public class TraceWebClientAutoConfigurationTests { @Qualifier("secondRestTemplate") RestTemplate secondRestTemplate() { RestTemplate restTemplate = new RestTemplate(); - restTemplate.setInterceptors( - Arrays.asList(new MyClientHttpRequestInterceptor(), + restTemplate + .setInterceptors(Arrays.asList(new MyClientHttpRequestInterceptor(), new MySecondClientHttpRequestInterceptor())); return restTemplate; } @@ -124,25 +129,31 @@ public class TraceWebClientAutoConfigurationTests { @Bean RestTemplateCustomizer myRestTemplateCustomizer() { return restTemplate -> { - restTemplate.getInterceptors().add(0, new MySecondClientHttpRequestInterceptor()); + restTemplate.getInterceptors().add(0, + new MySecondClientHttpRequestInterceptor()); }; } } + } class MyClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { - @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { return execution.execute(request, body); } + } class MySecondClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { - @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { return execution.execute(request, body); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientBeanPostProcessorTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientBeanPostProcessorTest.java index 2fd77c54b..c41db1898 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientBeanPostProcessorTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientBeanPostProcessorTest.java @@ -30,10 +30,13 @@ import org.springframework.web.reactive.function.client.WebClient; @RunWith(MockitoJUnitRunner.class) public class TraceWebClientBeanPostProcessorTest { - @Mock BeanFactory beanFactory; + @Mock + BeanFactory beanFactory; - @Test public void should_add_filter_only_once_to_web_client() { - TraceWebClientBeanPostProcessor processor = new TraceWebClientBeanPostProcessor(this.beanFactory); + @Test + public void should_add_filter_only_once_to_web_client() { + TraceWebClientBeanPostProcessor processor = new TraceWebClientBeanPostProcessor( + this.beanFactory); WebClient client = WebClient.create(); client = (WebClient) processor.postProcessAfterInitialization(client, "foo"); @@ -41,20 +44,27 @@ public class TraceWebClientBeanPostProcessorTest { client.mutate().filters(filters -> { BDDAssertions.then(filters).hasSize(1); - BDDAssertions.then(filters.get(0)).isInstanceOf(TraceExchangeFilterFunction.class); + BDDAssertions.then(filters.get(0)) + .isInstanceOf(TraceExchangeFilterFunction.class); }); } - @Test public void should_add_filter_only_once_to_web_client_via_builder() { - TraceWebClientBeanPostProcessor processor = new TraceWebClientBeanPostProcessor(this.beanFactory); + @Test + public void should_add_filter_only_once_to_web_client_via_builder() { + TraceWebClientBeanPostProcessor processor = new TraceWebClientBeanPostProcessor( + this.beanFactory); WebClient.Builder builder = WebClient.builder(); - builder = (WebClient.Builder) processor.postProcessAfterInitialization(builder, "foo"); - builder = (WebClient.Builder) processor.postProcessAfterInitialization(builder, "foo"); + builder = (WebClient.Builder) processor.postProcessAfterInitialization(builder, + "foo"); + builder = (WebClient.Builder) processor.postProcessAfterInitialization(builder, + "foo"); builder.build().mutate().filters(filters -> { BDDAssertions.then(filters).hasSize(1); - BDDAssertions.then(filters.get(0)).isInstanceOf(TraceExchangeFilterFunction.class); + BDDAssertions.then(filters.get(0)) + .isInstanceOf(TraceExchangeFilterFunction.class); }); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/discoveryexception/WebClientDiscoveryExceptionTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/discoveryexception/WebClientDiscoveryExceptionTests.java index 7126b3ad0..7af568704 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/discoveryexception/WebClientDiscoveryExceptionTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/discoveryexception/WebClientDiscoveryExceptionTests.java @@ -60,10 +60,18 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen @DirtiesContext public class WebClientDiscoveryExceptionTests { - @Autowired TestFeignInterfaceWithException testFeignInterfaceWithException; - @Autowired @LoadBalanced RestTemplate template; - @Autowired Tracer tracer; - @Autowired ArrayListSpanReporter reporter; + @Autowired + TestFeignInterfaceWithException testFeignInterfaceWithException; + + @Autowired + @LoadBalanced + RestTemplate template; + + @Autowired + Tracer tracer; + + @Autowired + ArrayListSpanReporter reporter; @Before public void close() { @@ -88,10 +96,8 @@ public class WebClientDiscoveryExceptionTests { // hystrix commands should finish at this point Thread.sleep(200); List spans = this.reporter.getSpans(); - then(spans.stream() - .filter(span1 -> span1.kind() == zipkin2.Span.Kind.CLIENT) - .findFirst() - .get().tags()).containsKey("error"); + then(spans.stream().filter(span1 -> span1.kind() == zipkin2.Span.Kind.CLIENT) + .findFirst().get().tags()).containsKey("error"); } @Test @@ -109,13 +115,15 @@ public class WebClientDiscoveryExceptionTests { @FeignClient("exceptionservice") public interface TestFeignInterfaceWithException { + @RequestMapping(method = RequestMethod.GET, value = "/") ResponseEntity shouldFailToConnect(); + } @Configuration - @EnableAutoConfiguration(exclude = {EurekaClientAutoConfiguration.class, - TraceWebServletAutoConfiguration.class}) + @EnableAutoConfiguration(exclude = { EurekaClientAutoConfiguration.class, + TraceWebServletAutoConfiguration.class }) @EnableDiscoveryClient @EnableFeignClients @RibbonClient("exceptionservice") @@ -127,18 +135,23 @@ public class WebClientDiscoveryExceptionTests { return new RestTemplate(); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean Reporter mySpanReporter() { + @Bean + Reporter mySpanReporter() { return new ArrayListSpanReporter(); } + } @FunctionalInterface interface ResponseEntityProvider { - ResponseEntity get( - WebClientDiscoveryExceptionTests webClientTests); + + ResponseEntity get(WebClientDiscoveryExceptionTests webClientTests); + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/exception/WebClientExceptionTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/exception/WebClientExceptionTests.java index 3c9181428..37f1775f9 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/exception/WebClientExceptionTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/exception/WebClientExceptionTests.java @@ -62,24 +62,35 @@ import static org.assertj.core.api.BDDAssertions.then; @RunWith(JUnitParamsRunner.class) @SpringBootTest(classes = { - WebClientExceptionTests.TestConfiguration.class }, - properties = {"ribbon.ConnectTimeout=30000", "spring.application.name=exceptionservice" }, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) + WebClientExceptionTests.TestConfiguration.class }, properties = { + "ribbon.ConnectTimeout=30000", + "spring.application.name=exceptionservice" }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class WebClientExceptionTests { - private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + private static final Log log = LogFactory + .getLog(MethodHandles.lookup().lookupClass()); @ClassRule public static final SpringClassRule SCR = new SpringClassRule(); + @Rule public final SpringMethodRule springMethodRule = new SpringMethodRule(); + @Rule public final OutputCapture capture = new OutputCapture(); - @Autowired TestFeignInterfaceWithException testFeignInterfaceWithException; - @Autowired @LoadBalanced RestTemplate template; - @Autowired Tracing tracer; - @Autowired ArrayListSpanReporter reporter; + @Autowired + TestFeignInterfaceWithException testFeignInterfaceWithException; + + @Autowired + @LoadBalanced + RestTemplate template; + + @Autowired + Tracing tracer; + + @Autowired + ArrayListSpanReporter reporter; @Before public void open() { @@ -100,7 +111,8 @@ public class WebClientExceptionTests { } catch (RuntimeException e) { // SleuthAssertions.then(e).hasRootCauseInstanceOf(IOException.class); - } finally { + } + finally { span.finish(); } @@ -119,8 +131,10 @@ public class WebClientExceptionTests { @FeignClient("exceptionservice") public interface TestFeignInterfaceWithException { + @RequestMapping(method = RequestMethod.GET, value = "/") ResponseEntity shouldFailToConnect(); + } @Configuration @@ -138,13 +152,16 @@ public class WebClientExceptionTests { return new RestTemplate(clientHttpRequestFactory); } - @Bean Sampler alwaysSampler() { + @Bean + Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean ArrayListSpanReporter accumulator() { + @Bean + ArrayListSpanReporter accumulator() { return new ArrayListSpanReporter(); } + } @Configuration @@ -162,7 +179,9 @@ public class WebClientExceptionTests { @FunctionalInterface interface ResponseEntityProvider { - ResponseEntity get( - WebClientExceptionTests webClientTests); + + ResponseEntity get(WebClientExceptionTests webClientTests); + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/exceptionresolver/Issue585Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/exceptionresolver/Issue585Tests.java index b0c6660bc..690ab24f9 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/exceptionresolver/Issue585Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/exceptionresolver/Issue585Tests.java @@ -52,8 +52,12 @@ import static org.assertj.core.api.BDDAssertions.then; public class Issue585Tests { TestRestTemplate testRestTemplate = new TestRestTemplate(); - @Autowired ArrayListSpanReporter reporter; - @LocalServerPort int port; + + @Autowired + ArrayListSpanReporter reporter; + + @LocalServerPort + int port; @Test public void should_report_span_when_using_custom_exception_resolver() { @@ -63,52 +67,56 @@ public class Issue585Tests { then(Tracing.current().tracer().currentSpan()).isNull(); then(entity.getStatusCode().value()).isEqualTo(500); - then(this.reporter.getSpans().get(0).tags()) - .containsEntry("custom", "tag") + then(this.reporter.getSpans().get(0).tags()).containsEntry("custom", "tag") .containsKeys("error"); } + } @SpringBootApplication class TestConfig { - @Bean ArrayListSpanReporter testSpanReporter() { + @Bean + ArrayListSpanReporter testSpanReporter() { return new ArrayListSpanReporter(); } - @Bean Sampler testSampler() { + @Bean + Sampler testSampler() { return Sampler.ALWAYS_SAMPLE; } + } @RestController class TestController { - private final static Logger logger = LoggerFactory.getLogger( - TestController.class); + private final static Logger logger = LoggerFactory.getLogger(TestController.class); @RequestMapping(value = "sleuthtest", method = RequestMethod.GET) public ResponseEntity testSleuth(@RequestParam String greeting) { if (greeting.equalsIgnoreCase("hello")) { return new ResponseEntity<>("Hello World", HttpStatus.OK); - } else { + } + else { throw new RuntimeException("This is a test error"); } } + } @ControllerAdvice class CustomExceptionHandler extends ResponseEntityExceptionHandler { private final static Logger logger = LoggerFactory - .getLogger( - CustomExceptionHandler.class); + .getLogger(CustomExceptionHandler.class); - @Autowired private Tracing tracer; + @Autowired + private Tracing tracer; @ExceptionHandler(value = { Exception.class }) - protected ResponseEntity handleDefaultError( - Exception ex, HttpServletRequest request) { + protected ResponseEntity handleDefaultError(Exception ex, + HttpServletRequest request) { ExceptionResponse exceptionResponse = new ExceptionResponse("ERR-01", ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR, request.getRequestURI(), Instant.now().toEpochMilli()); @@ -127,10 +135,15 @@ class CustomExceptionHandler extends ResponseEntityExceptionHandler { @JsonInclude(JsonInclude.Include.NON_NULL) class ExceptionResponse { + private String errorCode; + private String errorMessage; + private HttpStatus httpStatus; + private String path; + private Long epochTime; ExceptionResponse(String errorCode, String errorMessage, HttpStatus httpStatus, diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignRetriesTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignRetriesTests.java index 7984228dc..ea9dc4790 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignRetriesTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignRetriesTests.java @@ -57,23 +57,24 @@ public class FeignRetriesTests { @Rule public final MockWebServer server = new MockWebServer(); - @Mock BeanFactory beanFactory; + @Mock + BeanFactory beanFactory; ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + HttpTracing httpTracing = HttpTracing.newBuilder(this.tracing) - .clientParser(SleuthHttpParserAccessor.getClient()) - .build(); + .clientParser(SleuthHttpParserAccessor.getClient()).build(); @Before @After public void setup() { - BDDMockito.given(this.beanFactory.getBean(HttpTracing.class)).willReturn(this.httpTracing); + BDDMockito.given(this.beanFactory.getBean(HttpTracing.class)) + .willReturn(this.httpTracing); } @Test @@ -83,15 +84,16 @@ public class FeignRetriesTests { }; String url = "http://localhost:" + server.getPort(); - TestInterface api = - Feign.builder() - .client(new TracingFeignClient(this.httpTracing, client)) - .target(TestInterface.class, url); + TestInterface api = Feign.builder() + .client(new TracingFeignClient(this.httpTracing, client)) + .target(TestInterface.class, url); try { api.decodedPost(); failBecauseExceptionWasNotThrown(FeignException.class); - } catch (FeignException e) { } + } + catch (FeignException e) { + } } @Test @@ -103,32 +105,29 @@ public class FeignRetriesTests { // we simulate an exception only for the first request if (atomicInteger.get() == 1) { throw new IOException(); - } else { + } + else { // with the second retry (first retry) we send back good result - return Response.builder() - .status(200) - .reason("OK") - .headers(new HashMap<>()) - .body("OK", Charset.defaultCharset()) + return Response.builder().status(200).reason("OK") + .headers(new HashMap<>()).body("OK", Charset.defaultCharset()) .build(); } }; - TestInterface api = - Feign.builder() - .client(new TracingFeignClient(this.httpTracing, new Client() { - @Override public Response execute(Request request, - Request.Options options) throws IOException { - atomicInteger.incrementAndGet(); - return client.execute(request, options); - } - })) - .target(TestInterface.class, url); + TestInterface api = Feign.builder() + .client(new TracingFeignClient(this.httpTracing, new Client() { + @Override + public Response execute(Request request, Request.Options options) + throws IOException { + atomicInteger.incrementAndGet(); + return client.execute(request, options); + } + })).target(TestInterface.class, url); then(api.decodedPost()).isEqualTo("OK"); // request interception should take place only twice (1st request & 2nd retry) then(atomicInteger.get()).isEqualTo(2); - then(this.reporter.getSpans().get(0).tags()) - .containsEntry("error", "IOException"); + then(this.reporter.getSpans().get(0).tags()).containsEntry("error", + "IOException"); then(this.reporter.getSpans().get(1).kind().ordinal()) .isEqualTo(Span.Kind.CLIENT.ordinal()); } @@ -137,7 +136,7 @@ public class FeignRetriesTests { @RequestLine("POST /") String decodedPost(); + } - } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignAspectTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignAspectTests.java index 9a21cab18..d3dfe9c55 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignAspectTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignAspectTests.java @@ -41,31 +41,41 @@ import static org.mockito.Mockito.verify; */ @RunWith(MockitoJUnitRunner.class) public class TraceFeignAspectTests { - - @Mock BeanFactory beanFactory; - @Mock Client client; - @Mock ProceedingJoinPoint pjp; - @Mock TraceLoadBalancerFeignClient traceLoadBalancerFeignClient; + + @Mock + BeanFactory beanFactory; + + @Mock + Client client; + + @Mock + ProceedingJoinPoint pjp; + + @Mock + TraceLoadBalancerFeignClient traceLoadBalancerFeignClient; + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) + .addScopeDecorator(StrictScopeDecorator.create()).build()) .build(); + HttpTracing httpTracing = HttpTracing.newBuilder(this.tracing) - .clientParser(SleuthHttpParserAccessor.getClient()) - .build(); + .clientParser(SleuthHttpParserAccessor.getClient()).build(); + TraceFeignAspect traceFeignAspect; - + @Before public void setup() { this.traceFeignAspect = new TraceFeignAspect(this.beanFactory) { - @Override Object executeTraceFeignClient(Object bean, ProceedingJoinPoint pjp) throws IOException { + @Override + Object executeTraceFeignClient(Object bean, ProceedingJoinPoint pjp) + throws IOException { return null; } }; } - @Test + @Test public void should_wrap_feign_client_in_trace_representation() throws Throwable { given(this.pjp.getTarget()).willReturn(this.client); @@ -73,18 +83,21 @@ public class TraceFeignAspectTests { verify(this.pjp, never()).proceed(); } - - @Test - public void should_not_wrap_traced_feign_client_in_trace_representation() throws Throwable { - given(this.pjp.getTarget()).willReturn(new TracingFeignClient(this.httpTracing, this.client)); + + @Test + public void should_not_wrap_traced_feign_client_in_trace_representation() + throws Throwable { + given(this.pjp.getTarget()) + .willReturn(new TracingFeignClient(this.httpTracing, this.client)); this.traceFeignAspect.feignClientWasCalled(this.pjp); verify(this.pjp).proceed(); } - - @Test - public void should_not_wrap_traced_load_balancer_feign_client_in_trace_representation() throws Throwable { + + @Test + public void should_not_wrap_traced_load_balancer_feign_client_in_trace_representation() + throws Throwable { given(this.pjp.getTarget()).willReturn(this.traceLoadBalancerFeignClient); this.traceFeignAspect.feignClientWasCalled(this.pjp); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignClientTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignClientTests.java index 91911d101..2d2f778b6 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignClientTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignClientTests.java @@ -48,18 +48,23 @@ import static org.assertj.core.api.BDDAssertions.then; public class TracingFeignClientTests { ArrayListSpanReporter reporter = new ArrayListSpanReporter(); - @Mock BeanFactory beanFactory; + + @Mock + BeanFactory beanFactory; + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + Tracer tracer = this.tracing.tracer(); + HttpTracing httpTracing = HttpTracing.newBuilder(this.tracing) - .clientParser(SleuthHttpParserAccessor.getClient()) - .build(); - @Mock Client client; + .clientParser(SleuthHttpParserAccessor.getClient()).build(); + + @Mock + Client client; + Client traceFeignClient; @Before @@ -72,10 +77,13 @@ public class TracingFeignClientTests { Span span = this.tracer.nextSpan().name("foo"); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { - this.traceFeignClient.execute( - Request.create("GET", "http://foo", new HashMap<>(), "".getBytes(), - Charset.defaultCharset()), new Request.Options()); - } finally { + this.traceFeignClient + .execute( + Request.create("GET", "http://foo", new HashMap<>(), + "".getBytes(), Charset.defaultCharset()), + new Request.Options()); + } + finally { span.finish(); } @@ -90,26 +98,32 @@ public class TracingFeignClientTests { .willThrow(new RuntimeException("exception has occurred")); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) { - this.traceFeignClient.execute( - Request.create("GET", "http://foo", new HashMap<>(), "".getBytes(), - Charset.defaultCharset()), new Request.Options()); + this.traceFeignClient + .execute( + Request.create("GET", "http://foo", new HashMap<>(), + "".getBytes(), Charset.defaultCharset()), + new Request.Options()); BDDAssertions.fail("Exception should have been thrown"); - } catch (Exception e) { - } finally { + } + catch (Exception e) { + } + finally { span.finish(); } then(this.reporter.getSpans().get(0)).extracting("kind.ordinal") .contains(Span.Kind.CLIENT.ordinal()); - then(this.reporter.getSpans().get(0).tags()) - .containsEntry("error", "exception has occurred"); + then(this.reporter.getSpans().get(0).tags()).containsEntry("error", + "exception has occurred"); } @Test public void should_shorten_the_span_name() throws IOException { - this.traceFeignClient.execute( - Request.create("GET", "http://foo/" + bigName(), new HashMap<>(), "".getBytes(), - Charset.defaultCharset()), new Request.Options()); + this.traceFeignClient + .execute( + Request.create("GET", "http://foo/" + bigName(), new HashMap<>(), + "".getBytes(), Charset.defaultCharset()), + new Request.Options()); then(this.reporter.getSpans().get(0).name()).hasSize(50); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignObjectWrapperTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignObjectWrapperTests.java index d7a846b61..5f6cc53ef 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignObjectWrapperTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TracingFeignObjectWrapperTests.java @@ -36,18 +36,26 @@ import static org.mockito.Mockito.mock; public class TracingFeignObjectWrapperTests { Tracing tracing = Tracing.newBuilder().build(); + HttpTracing httpTracing = HttpTracing.create(this.tracing); - @Mock BeanFactory beanFactory; - @InjectMocks TraceFeignObjectWrapper traceFeignObjectWrapper; + + @Mock + BeanFactory beanFactory; + + @InjectMocks + TraceFeignObjectWrapper traceFeignObjectWrapper; @Test public void should_wrap_a_client_into_lazy_trace_client() throws Exception { - then(this.traceFeignObjectWrapper.wrap(mock(Client.class))).isExactlyInstanceOf(LazyTracingFeignClient.class); + then(this.traceFeignObjectWrapper.wrap(mock(Client.class))) + .isExactlyInstanceOf(LazyTracingFeignClient.class); } @Test public void should_not_wrap_a_bean_that_is_not_feign_related() throws Exception { String notFeignRelatedObject = "object"; - then(this.traceFeignObjectWrapper.wrap(notFeignRelatedObject)).isSameAs(notFeignRelatedObject); + then(this.traceFeignObjectWrapper.wrap(notFeignRelatedObject)) + .isSameAs(notFeignRelatedObject); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue307/Issue307Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue307/Issue307Tests.java index c122231c0..54b390e17 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue307/Issue307Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue307/Issue307Tests.java @@ -46,21 +46,23 @@ public class Issue307Tests { @Test public void should_start_context() { - try (ConfigurableApplicationContext applicationContext = SpringApplication - .run(SleuthSampleApplication.class, "--spring.jmx.enabled=false", "--server.port=0")) { + try (ConfigurableApplicationContext applicationContext = SpringApplication.run( + SleuthSampleApplication.class, "--spring.jmx.enabled=false", + "--server.port=0")) { } } + } @EnableAutoConfiguration -@Import({ ParticipantsBean.class}) +@Import({ ParticipantsBean.class }) @RestController @EnableFeignClients @EnableCircuitBreaker class SleuthSampleApplication { - private static final Logger LOG = LoggerFactory.getLogger( - SleuthSampleApplication.class.getName()); + private static final Logger LOG = LoggerFactory + .getLogger(SleuthSampleApplication.class.getName()); @Autowired private RestTemplate restTemplate; @@ -96,10 +98,12 @@ class SleuthSampleApplication { private int port() { return this.environment.getProperty("local.server.port", Integer.class); } + } @Component class ParticipantsBean { + @Autowired private ParticipantsClient participantsClient; @@ -111,12 +115,13 @@ class ParticipantsBean { public List defaultParticipants(String raceId) { return new ArrayList<>(); } + } @FeignClient("participants") interface ParticipantsClient { - @RequestMapping(method = RequestMethod.GET, value="/races/{raceId}") + @RequestMapping(method = RequestMethod.GET, value = "/races/{raceId}") List getParticipants(@PathVariable("raceId") String raceId); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue350/Issue350Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue350/Issue350Tests.java index 3c0668b94..72c686f58 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue350/Issue350Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue350/Issue350Tests.java @@ -50,15 +50,18 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = Application.class, - webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@TestPropertySource(properties = {"ribbon.eureka.enabled=false", - "feign.hystrix.enabled=false", "server.port=9988"}) +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@TestPropertySource(properties = { "ribbon.eureka.enabled=false", + "feign.hystrix.enabled=false", "server.port=9988" }) public class Issue350Tests { TestRestTemplate template = new TestRestTemplate(); - @Autowired Tracing tracer; - @Autowired ArrayListSpanReporter reporter; + + @Autowired + Tracing tracer; + + @Autowired + ArrayListSpanReporter reporter; @Before public void setup() { @@ -67,17 +70,19 @@ public class Issue350Tests { @Test public void should_successfully_work_without_hystrix() { - this.template.getForEntity("http://localhost:9988/sleuth/test-not-ok", String.class); + this.template.getForEntity("http://localhost:9988/sleuth/test-not-ok", + String.class); List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).tags()).containsEntry("http.status_code", "406"); } + } @Configuration @EnableAutoConfiguration(exclude = TraceWebServletAutoConfiguration.class) -@EnableFeignClients(basePackageClasses = { SleuthTestController.class}) +@EnableFeignClients(basePackageClasses = { SleuthTestController.class }) class Application { @Bean @@ -104,6 +109,7 @@ class Application { public Reporter spanReporter() { return new ArrayListSpanReporter(); } + } @RestController @@ -120,9 +126,10 @@ class ServiceTestController { public String notOk() throws InterruptedException, ExecutionException { return "Not OK"; } + } -@FeignClient(name="myFeignClient", url="localhost:9988") +@FeignClient(name = "myFeignClient", url = "localhost:9988") interface MyFeignClient { @RequestMapping("/service/ok") @@ -130,6 +137,7 @@ interface MyFeignClient { @RequestMapping("/service/not-ok") String exp(); + } @RestController @@ -148,5 +156,5 @@ class SleuthTestController { public String notOk() throws InterruptedException, ExecutionException { return myFeignClient.exp(); } -} +} diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue362/Issue362Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue362/Issue362Tests.java index 02b16dbdf..ae60cc5e2 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue362/Issue362Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue362/Issue362Tests.java @@ -63,16 +63,21 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = Application.class, - webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@TestPropertySource(properties = {"ribbon.eureka.enabled=false", - "feign.hystrix.enabled=false", "server.port=9998"}) +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@TestPropertySource(properties = { "ribbon.eureka.enabled=false", + "feign.hystrix.enabled=false", "server.port=9998" }) public class Issue362Tests { RestTemplate template = new RestTemplate(); - @Autowired FeignComponentAsserter feignComponentAsserter; - @Autowired Tracing tracer; - @Autowired ArrayListSpanReporter reporter; + + @Autowired + FeignComponentAsserter feignComponentAsserter; + + @Autowired + Tracing tracer; + + @Autowired + ArrayListSpanReporter reporter; @Before public void setup() { @@ -84,10 +89,12 @@ public class Issue362Tests { public void should_successfully_work_with_custom_error_decoder_when_sending_successful_request() { String securedURl = "http://localhost:9998/sleuth/test-ok"; - ResponseEntity response = this.template.getForEntity(securedURl, String.class); + ResponseEntity response = this.template.getForEntity(securedURl, + String.class); then(response.getBody()).isEqualTo("I'm OK"); - then(this.feignComponentAsserter.executedComponents).containsEntry(Client.class, true); + then(this.feignComponentAsserter.executedComponents).containsEntry(Client.class, + true); List spans = this.reporter.getSpans(); then(spans).hasSize(1); then(spans.get(0).tags()).containsEntry("http.path", "/service/ok"); @@ -100,7 +107,9 @@ public class Issue362Tests { try { this.template.getForEntity(securedURl, String.class); fail("should propagate an exception"); - } catch (Exception e) { } + } + catch (Exception e) { + } then(this.feignComponentAsserter.executedComponents) .containsEntry(ErrorDecoder.class, true) @@ -108,14 +117,15 @@ public class Issue362Tests { List spans = this.reporter.getSpans(); // retries then(spans).hasSize(5); - then(spans.stream().map(span -> span.tags().get("http.status_code")).collect( - Collectors.toList())).containsOnly("409"); + then(spans.stream().map(span -> span.tags().get("http.status_code")) + .collect(Collectors.toList())).containsOnly("409"); } + } @Configuration @EnableAutoConfiguration(exclude = TraceWebServletAutoConfiguration.class) -@EnableFeignClients(basePackageClasses = { SleuthTestController.class}) +@EnableFeignClients(basePackageClasses = { SleuthTestController.class }) class Application { @Bean @@ -139,7 +149,9 @@ class Application { } @Bean - public FeignComponentAsserter testHolder() { return new FeignComponentAsserter(); } + public FeignComponentAsserter testHolder() { + return new FeignComponentAsserter(); + } @Bean public Reporter spanReporter() { @@ -149,15 +161,16 @@ class Application { } class FeignComponentAsserter { + Map executedComponents = new ConcurrentHashMap<>(); + } @Configuration class CustomConfig { @Bean - public ErrorDecoder errorDecoder( - FeignComponentAsserter feignComponentAsserter) { + public ErrorDecoder errorDecoder(FeignComponentAsserter feignComponentAsserter) { return new CustomErrorDecoder(feignComponentAsserter); } @@ -170,8 +183,7 @@ class CustomConfig { private final FeignComponentAsserter feignComponentAsserter; - public CustomErrorDecoder( - FeignComponentAsserter feignComponentAsserter) { + public CustomErrorDecoder(FeignComponentAsserter feignComponentAsserter) { this.feignComponentAsserter = feignComponentAsserter; } @@ -180,15 +192,16 @@ class CustomConfig { this.feignComponentAsserter.executedComponents.put(ErrorDecoder.class, true); if (response.status() == 409) { return new RetryableException("Article not Ready", new Date()); - } else { + } + else { return super.decode(methodKey, response); } } + } @Bean - public Client client( - FeignComponentAsserter feignComponentAsserter) { + public Client client(FeignComponentAsserter feignComponentAsserter) { return new CustomClient(feignComponentAsserter); } @@ -196,22 +209,23 @@ class CustomConfig { private final FeignComponentAsserter feignComponentAsserter; - public CustomClient( - FeignComponentAsserter feignComponentAsserter) { + public CustomClient(FeignComponentAsserter feignComponentAsserter) { super(null, null); this.feignComponentAsserter = feignComponentAsserter; } - @Override public Response execute(Request request, Request.Options options) + @Override + public Response execute(Request request, Request.Options options) throws IOException { this.feignComponentAsserter.executedComponents.put(Client.class, true); return super.execute(request, options); } + } + } -@FeignClient(value="myFeignClient", url="http://localhost:9998", - configuration = CustomConfig.class) +@FeignClient(value = "myFeignClient", url = "http://localhost:9998", configuration = CustomConfig.class) interface MyFeignClient { @RequestMapping("/service/ok") @@ -219,6 +233,7 @@ interface MyFeignClient { @RequestMapping("/service/not-ok") String exp(); + } @RestController @@ -235,6 +250,7 @@ class ServiceTestController { public String notOk() throws InterruptedException, ExecutionException { return "Not OK"; } + } @RestController @@ -253,4 +269,5 @@ class SleuthTestController { public String notOk() throws InterruptedException, ExecutionException { return myFeignClient.exp(); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue393/Issue393Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue393/Issue393Tests.java index b1f2fd120..752723fd3 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue393/Issue393Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue393/Issue393Tests.java @@ -53,13 +53,17 @@ import static org.assertj.core.api.BDDAssertions.then; */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@TestPropertySource(properties = {"spring.application.name=demo-feign-uri", - "server.port=9978", "eureka.client.enabled=true", "ribbon.eureka.enabled=true"}) +@TestPropertySource(properties = { "spring.application.name=demo-feign-uri", + "server.port=9978", "eureka.client.enabled=true", "ribbon.eureka.enabled=true" }) public class Issue393Tests { RestTemplate template = new RestTemplate(); - @Autowired ArrayListSpanReporter reporter; - @Autowired Tracing tracer; + + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + Tracing tracer; @Before public void open() { @@ -76,9 +80,10 @@ public class Issue393Tests { List spans = this.reporter.getSpans(); // retries then(spans).hasSize(2); - then(spans.stream().map(span -> span.tags().get("http.path")).collect( - Collectors.toList())).containsOnly("/name/mikesarver"); + then(spans.stream().map(span -> span.tags().get("http.path")) + .collect(Collectors.toList())).containsOnly("/name/mikesarver"); } + } @Configuration @@ -88,8 +93,7 @@ public class Issue393Tests { class Application { @Bean - public DemoController demoController( - MyNameRemote myNameRemote) { + public DemoController demoController(MyNameRemote myNameRemote) { return new DemoController(myNameRemote); } @@ -116,12 +120,12 @@ class Application { } -@FeignClient(name="no-name", - url="http://localhost:9978") +@FeignClient(name = "no-name", url = "http://localhost:9978") interface MyNameRemote { @RequestMapping(value = "/name/{id}", method = RequestMethod.GET) String getName(@PathVariable("id") String id); + } @RestController @@ -129,8 +133,7 @@ class DemoController { private final MyNameRemote myNameRemote; - public DemoController( - MyNameRemote myNameRemote) { + public DemoController(MyNameRemote myNameRemote) { this.myNameRemote = myNameRemote; } @@ -143,4 +146,5 @@ class DemoController { public String getName(@PathVariable("name") String name) { return name; } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue502/Issue502Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue502/Issue502Tests.java index aee75ce6c..c50ffa362 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue502/Issue502Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/issues/issue502/Issue502Tests.java @@ -49,15 +49,21 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = Application.class, - webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = {"feign.hystrix.enabled=false"}) +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = { + "feign.hystrix.enabled=false" }) public class Issue502Tests { - @Autowired MyClient myClient; - @Autowired MyNameRemote myNameRemote; - @Autowired ArrayListSpanReporter reporter; - @Autowired Tracing tracer; + @Autowired + MyClient myClient; + + @Autowired + MyNameRemote myNameRemote; + + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + Tracing tracer; @Before public void open() { @@ -75,6 +81,7 @@ public class Issue502Tests { then(spans).hasSize(1); then(spans.get(0).tags().get("http.path")).isEqualTo("/"); } + } @Configuration @@ -99,28 +106,27 @@ class Application { } -@FeignClient(name="foo", - url="http://non.existing.url") +@FeignClient(name = "foo", url = "http://non.existing.url") interface MyNameRemote { @RequestMapping(value = "/", method = RequestMethod.GET) String get(); + } class MyClient implements Client { boolean wasCalled; - @Override public Response execute(Request request, Request.Options options) - throws IOException { + @Override + public Response execute(Request request, Request.Options options) throws IOException { this.wasCalled = true; - return Response.builder() - .body("foo", Charset.forName("UTF-8")) - .headers(new HashMap<>()) - .status(200).build(); + return Response.builder().body("foo", Charset.forName("UTF-8")) + .headers(new HashMap<>()).status(200).build(); } boolean wasCalled() { return this.wasCalled; } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/servererrors/FeignClientServerErrorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/servererrors/FeignClientServerErrorTests.java index bafbd0998..66867a91a 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/servererrors/FeignClientServerErrorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/feign/servererrors/FeignClientServerErrorTests.java @@ -70,21 +70,26 @@ import static org.assertj.core.api.BDDAssertions.then; * @author ryarabori */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = FeignClientServerErrorTests.TestConfiguration.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@TestPropertySource(properties = { - "spring.application.name=fooservice", - "feign.hystrix.enabled=true"}) +@SpringBootTest(classes = FeignClientServerErrorTests.TestConfiguration.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { "spring.application.name=fooservice", + "feign.hystrix.enabled=true" }) // TODO: TRY TO REPLICATE IT LOCALLY @Ignore("FAILS ON CI. DOESN'T PROPAGATE TRACING HEADERS TO ANOTHER THREAD") public class FeignClientServerErrorTests { private static final Log log = LogFactory.getLog(FeignClientServerErrorTests.class); - @Autowired TestFeignInterface feignInterface; - @Autowired TestFeignWithCustomConfInterface customConfFeignInterface; - @Autowired ArrayListSpanReporter reporter; - @Autowired Tracer tracer; + @Autowired + TestFeignInterface feignInterface; + + @Autowired + TestFeignWithCustomConfInterface customConfFeignInterface; + + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + Tracer tracer; @Before public void setup() { @@ -92,12 +97,14 @@ public class FeignClientServerErrorTests { } @Test - public void shouldCloseSpanOnInternalServerError(){ - try(Tracer.SpanInScope ws = tracer.withSpanInScope(tracer.nextSpan().name("foo").start())) { + public void shouldCloseSpanOnInternalServerError() { + try (Tracer.SpanInScope ws = tracer + .withSpanInScope(tracer.nextSpan().name("foo").start())) { log.info("sending a request"); this.feignInterface.internalError(); fail("Must throw an exception"); - } catch (HystrixRuntimeException e) { + } + catch (HystrixRuntimeException e) { log.info("Expected exception thrown", e); } @@ -107,19 +114,20 @@ public class FeignClientServerErrorTests { Optional spanWithError = spans.stream() .filter(span -> span.tags().containsKey("error")).findFirst(); then(spanWithError.isPresent()).isTrue(); - then(spanWithError.get().tags()) - .containsEntry("error", "500") + then(spanWithError.get().tags()).containsEntry("error", "500") .containsEntry("http.status_code", "500"); }); } @Test public void shouldCloseSpanOnNotFound() { - try(Tracer.SpanInScope ws = tracer.withSpanInScope(tracer.nextSpan().name("foo").start())) { + try (Tracer.SpanInScope ws = tracer + .withSpanInScope(tracer.nextSpan().name("foo").start())) { log.info("sending a request"); this.feignInterface.notFound(); fail("Must throw an exception"); - } catch (HystrixRuntimeException e) { + } + catch (HystrixRuntimeException e) { log.info("Expected exception thrown", e); } @@ -127,19 +135,21 @@ public class FeignClientServerErrorTests { List spans = this.reporter.getSpans(); log.info("Spans " + spans); Optional spanWithError = spans.stream() - .filter(span -> span.tags().containsKey("http.status_code")).findFirst(); + .filter(span -> span.tags().containsKey("http.status_code")) + .findFirst(); then(spanWithError.isPresent()).isTrue(); - then(spanWithError.get().tags()) - .containsEntry("http.status_code", "404"); + then(spanWithError.get().tags()).containsEntry("http.status_code", "404"); }); } @Test public void shouldCloseSpanOnOk() { - try(Tracer.SpanInScope ws = tracer.withSpanInScope(tracer.nextSpan().name("foo").start())) { + try (Tracer.SpanInScope ws = tracer + .withSpanInScope(tracer.nextSpan().name("foo").start())) { log.info("sending a request"); this.feignInterface.ok(); - } catch (HystrixRuntimeException e) { + } + catch (HystrixRuntimeException e) { log.info("Expected exception thrown", e); } @@ -149,19 +159,20 @@ public class FeignClientServerErrorTests { Optional httpSpan = spans.stream() .filter(span -> span.tags().containsKey("http.method")).findFirst(); then(httpSpan.isPresent()).isTrue(); - then(httpSpan.get().tags()) - .containsEntry("http.method", "GET") + then(httpSpan.get().tags()).containsEntry("http.method", "GET") .doesNotContainEntry("http.url", "http://fooservice/ok"); }); } @Test - public void shouldCloseSpanOnOkWithCustomFeignConfiguration(){ - try(Tracer.SpanInScope ws = tracer.withSpanInScope(tracer.nextSpan().name("foo").start())) { + public void shouldCloseSpanOnOkWithCustomFeignConfiguration() { + try (Tracer.SpanInScope ws = tracer + .withSpanInScope(tracer.nextSpan().name("foo").start())) { log.info("sending a request"); this.customConfFeignInterface.ok(); fail("Must throw an exception"); - } catch (HystrixRuntimeException e) { + } + catch (HystrixRuntimeException e) { log.info("Expected exception thrown", e); } @@ -172,18 +183,19 @@ public class FeignClientServerErrorTests { Optional httpSpan = spans.stream() .filter(span -> span.tags().containsKey("http.method")).findFirst(); then(httpSpan.isPresent()).isTrue(); - then(httpSpan.get().tags()) - .containsEntry("http.method", "GET"); + then(httpSpan.get().tags()).containsEntry("http.method", "GET"); }); } @Test - public void shouldCloseSpanOnNotFoundWithCustomFeignConfiguration(){ - try(Tracer.SpanInScope ws = tracer.withSpanInScope(tracer.nextSpan().name("foo").start())) { + public void shouldCloseSpanOnNotFoundWithCustomFeignConfiguration() { + try (Tracer.SpanInScope ws = tracer + .withSpanInScope(tracer.nextSpan().name("foo").start())) { log.info("sending a request"); this.customConfFeignInterface.notFound(); fail("Must throw an exception"); - } catch (HystrixRuntimeException e) { + } + catch (HystrixRuntimeException e) { log.info("Expected exception thrown", e); } @@ -193,8 +205,7 @@ public class FeignClientServerErrorTests { Optional spanWithError = spans.stream() .filter(span -> span.tags().containsKey("error")).findFirst(); then(spanWithError.isPresent()).isTrue(); - then(spanWithError.get().tags()) - .containsEntry("error", "404") + then(spanWithError.get().tags()).containsEntry("error", "404") .containsEntry("http.status_code", "404"); }); } @@ -202,10 +213,9 @@ public class FeignClientServerErrorTests { @Configuration @EnableAutoConfiguration(exclude = TraceWebServletAutoConfiguration.class) @EnableFeignClients - @RibbonClients({@RibbonClient(value = "fooservice", - configuration = SimpleRibbonClientConfiguration.class), - @RibbonClient(value = "customConfFooService", - configuration = SimpleRibbonClientConfiguration.class)}) + @RibbonClients({ + @RibbonClient(value = "fooservice", configuration = SimpleRibbonClientConfiguration.class), + @RibbonClient(value = "customConfFooService", configuration = SimpleRibbonClientConfiguration.class) }) public static class TestConfiguration { @Bean @@ -233,6 +243,7 @@ public class FeignClientServerErrorTests { Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } + } @FeignClient(value = "fooservice") @@ -246,6 +257,7 @@ public class FeignClientServerErrorTests { @RequestMapping(method = RequestMethod.GET, value = "/ok") ResponseEntity ok(); + } @FeignClient(value = "customConfFooService", configuration = CustomFeignClientConfiguration.class) @@ -256,10 +268,12 @@ public class FeignClientServerErrorTests { @RequestMapping(method = RequestMethod.GET, value = "/ok") ResponseEntity ok(); + } @Configuration public static class CustomFeignClientConfiguration { + @Bean Decoder decoder() { return new Decoder.Default(); @@ -269,12 +283,14 @@ public class FeignClientServerErrorTests { ErrorDecoder errorDecoder() { return new ErrorDecoder.Default(); } + } @RestController public static class FooController { - @Autowired Tracing tracer; + @Autowired + Tracing tracer; @RequestMapping("/internalerror") public ResponseEntity internalError( @@ -297,8 +313,7 @@ public class FeignClientServerErrorTests { } @RequestMapping("/ok") - public ResponseEntity ok( - @RequestHeader("X-B3-TraceId") String traceId, + public ResponseEntity ok(@RequestHeader("X-B3-TraceId") String traceId, @RequestHeader("X-B3-SpanId") String spanId, @RequestHeader("X-B3-ParentSpanId") String parentId) { log.info("Will respond with OK"); @@ -307,8 +322,10 @@ public class FeignClientServerErrorTests { } private void logHeaders(String traceId, String spanId, String parentId) { - log.info("Trace [" + traceId + "], span [" + spanId + "], parent [" + parentId + "]"); + log.info("Trace [" + traceId + "], span [" + spanId + "], parent [" + parentId + + "]"); } + } @Configuration @@ -324,6 +341,7 @@ public class FeignClientServerErrorTests { Collections.singletonList(new Server("localhost", this.port))); return balancer; } + } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/integration/WebClientTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/integration/WebClientTests.java index 3cb6d4141..ce0053afb 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/integration/WebClientTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/integration/WebClientTests.java @@ -97,38 +97,68 @@ import static org.assertj.core.api.Assertions.fail; import static org.assertj.core.api.BDDAssertions.then; @RunWith(JUnitParamsRunner.class) -@SpringBootTest(classes = WebClientTests.TestConfiguration.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@TestPropertySource(properties = { - "spring.sleuth.http.legacy.enabled=true", - "spring.application.name=fooservice", - "feign.hystrix.enabled=false" }) +@SpringBootTest(classes = WebClientTests.TestConfiguration.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { "spring.sleuth.http.legacy.enabled=true", + "spring.application.name=fooservice", "feign.hystrix.enabled=false" }) @DirtiesContext public class WebClientTests { + static final String TRACE_ID_NAME = "X-B3-TraceId"; static final String SPAN_ID_NAME = "X-B3-SpanId"; static final String SAMPLED_NAME = "X-B3-Sampled"; static final String PARENT_ID_NAME = "X-B3-ParentSpanId"; - private static final org.apache.commons.logging.Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + private static final org.apache.commons.logging.Log log = LogFactory + .getLog(MethodHandles.lookup().lookupClass()); - @ClassRule public static final SpringClassRule SCR = new SpringClassRule(); - @Rule public final SpringMethodRule springMethodRule = new SpringMethodRule(); + @ClassRule + public static final SpringClassRule SCR = new SpringClassRule(); - @Autowired TestFeignInterface testFeignInterface; - @Autowired @LoadBalanced RestTemplate template; - @Autowired WebClient webClient; - @Autowired WebClient.Builder webClientBuilder; - @Autowired HttpClientBuilder httpClientBuilder; // #845 - @Autowired HttpClient nettyHttpClient; - @Autowired HttpAsyncClientBuilder httpAsyncClientBuilder; // #845 - @Autowired ArrayListSpanReporter reporter; - @Autowired Tracer tracer; - @Autowired TestErrorController testErrorController; - @Autowired RestTemplateBuilder restTemplateBuilder; - @LocalServerPort int port; - @Autowired FooController fooController; - @Autowired MyRestTemplateCustomizer customizer; + @Rule + public final SpringMethodRule springMethodRule = new SpringMethodRule(); + + @Autowired + TestFeignInterface testFeignInterface; + + @Autowired + @LoadBalanced + RestTemplate template; + + @Autowired + WebClient webClient; + + @Autowired + WebClient.Builder webClientBuilder; + + @Autowired + HttpClientBuilder httpClientBuilder; // #845 + + @Autowired + HttpClient nettyHttpClient; + + @Autowired + HttpAsyncClientBuilder httpAsyncClientBuilder; // #845 + + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + Tracer tracer; + + @Autowired + TestErrorController testErrorController; + + @Autowired + RestTemplateBuilder restTemplateBuilder; + + @LocalServerPort + int port; + + @Autowired + FooController fooController; + + @Autowired + MyRestTemplateCustomizer customizer; @After public void close() { @@ -156,13 +186,15 @@ public class WebClientTests { List spans = this.reporter.getSpans(); then(spans).isNotEmpty(); Optional noTraceSpan = new ArrayList<>(spans).stream() - .filter(span -> "http:/notrace".equals(span.name()) && !span.tags() - .isEmpty() && span.tags().containsKey("http.path")).findFirst(); + .filter(span -> "http:/notrace".equals(span.name()) + && !span.tags().isEmpty() + && span.tags().containsKey("http.path")) + .findFirst(); then(noTraceSpan.isPresent()).isTrue(); - then(noTraceSpan.get().tags()) - .containsEntry("http.path", "/notrace") + then(noTraceSpan.get().tags()).containsEntry("http.path", "/notrace") .containsEntry("http.method", "GET"); - // TODO: matches cause there is an issue with Feign not providing the full URL at the interceptor level + // TODO: matches cause there is an issue with Feign not providing the full URL + // at the interceptor level then(noTraceSpan.get().tags().get("http.url")).matches(".*/notrace"); }); then(Tracing.current().tracer().currentSpan()).isNull(); @@ -178,23 +210,30 @@ public class WebClientTests { (ResponseEntityProvider) (tests) -> tests.testFeignInterface.getNoTrace(), (ResponseEntityProvider) (tests) -> tests.testFeignInterface.getNoTrace(), (ResponseEntityProvider) (tests) -> tests.testFeignInterface.getNoTrace(), - (ResponseEntityProvider) (tests) -> tests.template.getForEntity("http://fooservice/notrace", String.class), - (ResponseEntityProvider) (tests) -> tests.template.getForEntity("http://fooservice/notrace", String.class), - (ResponseEntityProvider) (tests) -> tests.template.getForEntity("http://fooservice/notrace", String.class), - (ResponseEntityProvider) (tests) -> tests.template.getForEntity("http://fooservice/notrace", String.class), - (ResponseEntityProvider) (tests) -> tests.template.getForEntity("http://fooservice/notrace", String.class), - (ResponseEntityProvider) (tests) -> tests.template.getForEntity("http://fooservice/notrace", String.class), - (ResponseEntityProvider) (tests) -> tests.template.getForEntity("http://fooservice/notrace", String.class), - (ResponseEntityProvider) (tests) -> tests.template.getForEntity("http://fooservice/notrace", String.class) - }; + (ResponseEntityProvider) (tests) -> tests.template + .getForEntity("http://fooservice/notrace", String.class), + (ResponseEntityProvider) (tests) -> tests.template + .getForEntity("http://fooservice/notrace", String.class), + (ResponseEntityProvider) (tests) -> tests.template + .getForEntity("http://fooservice/notrace", String.class), + (ResponseEntityProvider) (tests) -> tests.template + .getForEntity("http://fooservice/notrace", String.class), + (ResponseEntityProvider) (tests) -> tests.template + .getForEntity("http://fooservice/notrace", String.class), + (ResponseEntityProvider) (tests) -> tests.template + .getForEntity("http://fooservice/notrace", String.class), + (ResponseEntityProvider) (tests) -> tests.template + .getForEntity("http://fooservice/notrace", String.class), + (ResponseEntityProvider) (tests) -> tests.template + .getForEntity("http://fooservice/notrace", String.class) }; } @Test @Parameters @SuppressWarnings("unchecked") public void shouldPropagateNotSamplingHeader(ResponseEntityProvider provider) { - Span span = this.tracer.nextSpan( - TraceContextOrSamplingFlags.create(SamplingFlags.NOT_SAMPLED)) + Span span = this.tracer + .nextSpan(TraceContextOrSamplingFlags.create(SamplingFlags.NOT_SAMPLED)) .name("foo").start(); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { @@ -202,7 +241,8 @@ public class WebClientTests { then(response.getBody().get(TRACE_ID_NAME.toLowerCase())).isNotNull(); then(response.getBody().get(SAMPLED_NAME.toLowerCase())).isEqualTo("0"); - } finally { + } + finally { span.finish(); } @@ -231,7 +271,8 @@ public class WebClientTests { // we don't want to respond with any tracing data then(getHeader(response, SAMPLED_NAME)).isNull(); then(getHeader(response, TRACE_ID_NAME)).isNull(); - } finally { + } + finally { span.finish(); } @@ -242,88 +283,79 @@ public class WebClientTests { @Ignore("reactor is broken") @Test @SuppressWarnings("unchecked") - public void shouldAttachTraceIdWhenCallingAnotherServiceForNettyHttpClient() throws Exception { + public void shouldAttachTraceIdWhenCallingAnotherServiceForNettyHttpClient() + throws Exception { Span span = this.tracer.nextSpan().name("foo").start(); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { - HttpClientResponse response = this.nettyHttpClient - .get() - .uri("http://localhost:" + port) - .response() - .block(); + HttpClientResponse response = this.nettyHttpClient.get() + .uri("http://localhost:" + port).response().block(); then(response).isNotNull(); } then(this.tracer.currentSpan()).isNull(); - then(this.reporter.getSpans()) - .isNotEmpty() - .extracting("traceId", String.class) + then(this.reporter.getSpans()).isNotEmpty().extracting("traceId", String.class) .containsOnly(span.context().traceIdString()); - then(this.reporter.getSpans()) - .extracting("kind.name") - .contains("CLIENT"); + then(this.reporter.getSpans()).extracting("kind.name").contains("CLIENT"); } @Test @SuppressWarnings("unchecked") - public void shouldAttachTraceIdWhenCallingAnotherServiceForHttpClient() throws Exception { + public void shouldAttachTraceIdWhenCallingAnotherServiceForHttpClient() + throws Exception { Span span = this.tracer.nextSpan().name("foo").start(); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { - String response = this.httpClientBuilder.build() - .execute(new HttpGet("http://localhost:" + port), - new BasicResponseHandler()); + String response = this.httpClientBuilder.build().execute( + new HttpGet("http://localhost:" + port), new BasicResponseHandler()); then(response).isNotEmpty(); } then(this.tracer.currentSpan()).isNull(); - then(this.reporter.getSpans()) - .isNotEmpty() - .extracting("traceId", String.class) + then(this.reporter.getSpans()).isNotEmpty().extracting("traceId", String.class) .containsOnly(span.context().traceIdString()); - then(this.reporter.getSpans()) - .extracting("kind.name") - .contains("CLIENT"); + then(this.reporter.getSpans()).extracting("kind.name").contains("CLIENT"); } @Test @SuppressWarnings("unchecked") - public void shouldAttachTraceIdWhenCallingAnotherServiceForAsyncHttpClient() throws Exception { + public void shouldAttachTraceIdWhenCallingAnotherServiceForAsyncHttpClient() + throws Exception { Span span = this.tracer.nextSpan().name("foo").start(); CloseableHttpAsyncClient client = this.httpAsyncClientBuilder.build(); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { client.start(); - Future future = client - .execute(new HttpGet("http://localhost:" + port), - new FutureCallback() { - @Override public void completed(HttpResponse result) { + Future future = client.execute( + new HttpGet("http://localhost:" + port), + new FutureCallback() { + @Override + public void completed(HttpResponse result) { - } + } - @Override public void failed(Exception ex) { + @Override + public void failed(Exception ex) { - } + } - @Override public void cancelled() { + @Override + public void cancelled() { - } - }); + } + }); then(future.get()).isNotNull(); - } finally { + } + finally { client.close(); } then(this.tracer.currentSpan()).isNull(); - then(this.reporter.getSpans()) - .isNotEmpty() - .extracting("traceId", String.class) + then(this.reporter.getSpans()).isNotEmpty().extracting("traceId", String.class) .containsOnly(span.context().traceIdString()); - then(this.reporter.getSpans()) - .extracting("kind.name") - .contains("CLIENT"); + then(this.reporter.getSpans()).extracting("kind.name").contains("CLIENT"); } @Test @@ -332,18 +364,14 @@ public class WebClientTests { Span span = this.tracer.nextSpan().name("foo").start(); try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { - this.webClient.get() - .uri("http://localhost:" + this.port + "/traceid") - .retrieve() - .bodyToMono(String.class) - .block(); - } finally { + this.webClient.get().uri("http://localhost:" + this.port + "/traceid") + .retrieve().bodyToMono(String.class).block(); + } + finally { span.finish(); } then(this.tracer.currentSpan()).isNull(); - then(this.reporter.getSpans()) - .isNotEmpty() - .extracting("kind.name") + then(this.reporter.getSpans()).isNotEmpty().extracting("kind.name") .contains("CLIENT"); } @@ -362,7 +390,8 @@ public class WebClientTests { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { provider.get(this); - } finally { + } + finally { span.finish(); } @@ -372,11 +401,10 @@ public class WebClientTests { Object[] parametersForShouldAttachTraceIdWhenUsingFeignClientWithoutResponseBody() { return new Object[] { - (ResponseEntityProvider) (tests) -> - tests.testFeignInterface.noResponseBody(), - (ResponseEntityProvider) (tests) -> - tests.template.getForEntity("http://fooservice/noresponse", String.class) - }; + (ResponseEntityProvider) (tests) -> tests.testFeignInterface + .noResponseBody(), + (ResponseEntityProvider) (tests) -> tests.template + .getForEntity("http://fooservice/noresponse", String.class) }; } @Test @@ -384,25 +412,26 @@ public class WebClientTests { try { this.template.getForEntity("http://fooservice/nonExistent", String.class); fail("An exception should be thrown"); - } catch (HttpClientErrorException e) { } + } + catch (HttpClientErrorException e) { + } then(this.tracer.currentSpan()).isNull(); Optional storedSpan = this.reporter.getSpans().stream() - .filter(span -> "404".equals(span.tags().get("http.status_code"))).findFirst(); + .filter(span -> "404".equals(span.tags().get("http.status_code"))) + .findFirst(); then(storedSpan.isPresent()).isTrue(); List spans = this.reporter.getSpans(); - spans.stream() - .forEach(span -> { - int initialSize = span.annotations().size(); - int distinctSize = span.annotations().stream().map(Annotation::value).distinct() - .collect(Collectors.toList()).size(); - log.info("logs " + span.annotations()); - then(initialSize).as("there are no duplicate log entries").isEqualTo(distinctSize); - }); + spans.stream().forEach(span -> { + int initialSize = span.annotations().size(); + int distinctSize = span.annotations().stream().map(Annotation::value) + .distinct().collect(Collectors.toList()).size(); + log.info("logs " + span.annotations()); + then(initialSize).as("there are no duplicate log entries") + .isEqualTo(distinctSize); + }); - then(this.reporter.getSpans()) - .isNotEmpty() - .extracting("kind.name") + then(this.reporter.getSpans()).isNotEmpty().extracting("kind.name") .contains("CLIENT"); } @@ -421,15 +450,15 @@ public class WebClientTests { try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) { RestTemplate template = this.restTemplateBuilder.build(); - template.getForObject("http://localhost:" + this.port + "/traceid", String.class); - } finally { + template.getForObject("http://localhost:" + this.port + "/traceid", + String.class); + } + finally { span.finish(); } then(this.tracer.currentSpan()).isNull(); then(this.customizer.isExecuted()).isTrue(); - then(this.reporter.getSpans()) - .extracting("kind.name") - .contains("CLIENT"); + then(this.reporter.getSpans()).extracting("kind.name").contains("CLIENT"); } private String getHeader(ResponseEntity response, String name) { @@ -439,6 +468,7 @@ public class WebClientTests { @FeignClient("fooservice") public interface TestFeignInterface { + @RequestMapping(method = RequestMethod.GET, value = "/traceid") ResponseEntity getTraceId(); @@ -450,6 +480,7 @@ public class WebClientTests { @RequestMapping(method = RequestMethod.GET, value = "/noresponse") ResponseEntity noResponseBody(); + } @Configuration @@ -469,16 +500,19 @@ public class WebClientTests { return new RestTemplate(); } - @Bean Sampler testSampler() { + @Bean + Sampler testSampler() { return Sampler.ALWAYS_SAMPLE; } @Bean - TestErrorController testErrorController(ErrorAttributes errorAttributes, Tracing tracer) { + TestErrorController testErrorController(ErrorAttributes errorAttributes, + Tracing tracer) { return new TestErrorController(errorAttributes, tracer.tracer()); } - @Bean Reporter spanReporter() { + @Bean + Reporter spanReporter() { return new ArrayListSpanReporter(); } @@ -497,21 +531,26 @@ public class WebClientTests { return new MyRestTemplateCustomizer(); } - @Bean HttpClient reactorHttpClient() { + @Bean + HttpClient reactorHttpClient() { return HttpClient.create(); } + } static class MyRestTemplateCustomizer implements RestTemplateCustomizer { + boolean executed; - @Override public void customize(RestTemplate restTemplate) { + @Override + public void customize(RestTemplate restTemplate) { this.executed = true; } public boolean isExecuted() { return executed; } + } public static class TestErrorController extends BasicErrorController { @@ -538,6 +577,7 @@ public class WebClientTests { public void clear() { this.span = null; } + } @RestController @@ -591,6 +631,7 @@ public class WebClientTests { public void clear() { this.span = null; } + } @Configuration @@ -606,12 +647,15 @@ public class WebClientTests { Collections.singletonList(new Server("localhost", this.port))); return balancer; } + } @FunctionalInterface interface ResponseEntityProvider { + @SuppressWarnings("rawtypes") - ResponseEntity get( - WebClientTests webClientTests); + ResponseEntity get(WebClientTests webClientTests); + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/issues/issue971/DemoSleuthSkipApplicationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/issues/issue971/DemoSleuthSkipApplicationTests.java index d1800d7d6..be79c7f17 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/issues/issue971/DemoSleuthSkipApplicationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/issues/issue971/DemoSleuthSkipApplicationTests.java @@ -35,22 +35,26 @@ import org.springframework.web.client.RestTemplate; import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringRunner.class) -@SpringBootTest(classes = DemoSleuthSkipApplicationTests.Config.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = { "management.endpoints.web.exposure.include:*", - "server.servlet.context-path:/context-path", - "spring.sleuth.http.legacy.enabled:true"}) +@SpringBootTest(classes = DemoSleuthSkipApplicationTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { + "management.endpoints.web.exposure.include:*", + "server.servlet.context-path:/context-path", + "spring.sleuth.http.legacy.enabled:true" }) public class DemoSleuthSkipApplicationTests { - @Autowired ArrayListSpanReporter accumulator; - @Autowired Tracer tracer; + @Autowired + ArrayListSpanReporter accumulator; - @LocalServerPort int port; + @Autowired + Tracer tracer; + + @LocalServerPort + int port; @Test public void should_not_sample_skipped_endpoint_with_context_path() { - new RestTemplate().getForObject("http://localhost:" + - this.port + "/context-path/actuator/health", String.class); + new RestTemplate().getForObject( + "http://localhost:" + this.port + "/context-path/actuator/health", + String.class); then(this.tracer.currentSpan()).isNull(); then(this.accumulator.getSpans()).hasSize(0); @@ -61,12 +65,16 @@ public class DemoSleuthSkipApplicationTests { @DisableSecurity public static class Config { - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/view/Issue469.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/view/Issue469.java index 45c5a6e82..c92e0be76 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/view/Issue469.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/view/Issue469.java @@ -28,15 +28,19 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter @Configuration public class Issue469 extends WebMvcConfigurerAdapter { - @Override public void addViewControllers(ViewControllerRegistry registry) { + @Override + public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/welcome").setViewName("welcome"); } - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/view/Issue469Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/view/Issue469Tests.java index e40eb954e..e11281013 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/view/Issue469Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/view/Issue469Tests.java @@ -29,22 +29,27 @@ import org.springframework.web.client.RestTemplate; import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringRunner.class) -@SpringBootTest(classes = Issue469.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@TestPropertySource(properties = {"spring.mvc.view.prefix=/WEB-INF/jsp/", - "spring.mvc.view.suffix=.jsp"}) +@SpringBootTest(classes = Issue469.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(properties = { "spring.mvc.view.prefix=/WEB-INF/jsp/", + "spring.mvc.view.suffix=.jsp" }) public class Issue469Tests { - @Autowired ArrayListSpanReporter reporter; - @Autowired Environment environment; + @Autowired + ArrayListSpanReporter reporter; + + @Autowired + Environment environment; + RestTemplate restTemplate = new RestTemplate(); @Test - public void should_not_result_in_tracing_exceptions_when_using_view_controllers() throws Exception { + public void should_not_result_in_tracing_exceptions_when_using_view_controllers() + throws Exception { try { - this.restTemplate - .getForObject("http://localhost:" + port() + "/welcome", String.class); - } catch (Exception e) { + this.restTemplate.getForObject("http://localhost:" + port() + "/welcome", + String.class); + } + catch (Exception e) { // JSPs are not rendered then(e).hasMessageContaining("404"); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilterTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilterTests.java index 79e98a3fc..ecbb34acb 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilterTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilterTests.java @@ -49,21 +49,25 @@ import static org.assertj.core.api.BDDAssertions.then; @RunWith(MockitoJUnitRunner.class) public class TracePostZuulFilterTests { - @Mock HttpServletRequest httpServletRequest; - @Mock HttpServletResponse httpServletResponse; + @Mock + HttpServletRequest httpServletRequest; + + @Mock + HttpServletResponse httpServletResponse; ArrayListSpanReporter reporter = new ArrayListSpanReporter(); + Tracing tracing = Tracing.newBuilder() .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() - .addScopeDecorator(StrictScopeDecorator.create()) - .build()) - .spanReporter(this.reporter) - .build(); + .addScopeDecorator(StrictScopeDecorator.create()).build()) + .spanReporter(this.reporter).build(); + HttpTracing httpTracing = HttpTracing.newBuilder(this.tracing) .clientParser(SleuthHttpParserAccessor.getClient()) - .serverParser(SleuthHttpParserAccessor.getServer(new ErrorParser())) - .build(); + .serverParser(SleuthHttpParserAccessor.getServer(new ErrorParser())).build(); + private TracePostZuulFilter filter = new TracePostZuulFilter(this.httpTracing); + RequestContext requestContext = new RequestContext(); @After @@ -103,16 +107,17 @@ public class TracePostZuulFilterTests { try (Tracer.SpanInScope ws = this.tracing.tracer().withSpanInScope(span)) { this.filter.runFilter(); - } finally { + } + finally { span.finish(); } List spans = this.reporter.getSpans(); then(spans).hasSize(1); // initial span - then(spans.get(0).tags()) - .containsEntry("http.status_code", "456"); + then(spans.get(0).tags()).containsEntry("http.status_code", "456"); then(spans.get(0).name()).isEqualTo("http:start"); then(this.tracing.tracer().currentSpan()).isNull(); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulIntegrationTests.java index b68a54cd8..28abd22a3 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulIntegrationTests.java @@ -75,14 +75,18 @@ import static org.assertj.core.api.BDDAssertions.then; @DirtiesContext public class TraceZuulIntegrationTests { - private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + private static final Log log = LogFactory + .getLog(MethodHandles.lookup().lookupClass()); @Value("${local.server.port}") private int port; + @Autowired Tracing tracing; + @Autowired ArrayListSpanReporter spanAccumulator; + @Autowired RestTemplate restTemplate; @@ -103,10 +107,12 @@ public class TraceZuulIntegrationTests { then(result.getStatusCode()).isEqualTo(HttpStatus.OK); then(result.getBody()).isEqualTo("Hello world"); - } catch (Exception e) { + } + catch (Exception e) { log.error(e); throw e; - } finally { + } + finally { span.finish(); } @@ -127,7 +133,8 @@ public class TraceZuulIntegrationTests { HttpMethod.GET, new HttpEntity<>((Void) null), String.class); then(result.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - } finally { + } + finally { span.finish(); } @@ -140,8 +147,7 @@ public class TraceZuulIntegrationTests { void everySpanHasTheSameTraceId(List actual) { BDDAssertions.assertThat(actual).isNotNull(); - List traceIds = actual.stream() - .map(zipkin2.Span::traceId).distinct() + List traceIds = actual.stream().map(zipkin2.Span::traceId).distinct() .collect(toList()); log.info("Stored traceids " + traceIds); assertThat(traceIds).hasSize(1); @@ -151,16 +157,15 @@ public class TraceZuulIntegrationTests { BDDAssertions.assertThat(actual).isNotNull(); List parentSpanIds = actual.stream().map(zipkin2.Span::parentId) .filter(Objects::nonNull).collect(toList()); - List spanIds = actual.stream() - .map(zipkin2.Span::id).distinct() + List spanIds = actual.stream().map(zipkin2.Span::id).distinct() .collect(toList()); List difference = new ArrayList<>(parentSpanIds); difference.removeAll(spanIds); - log.info("Difference between parent ids and span ids " + - difference.stream().map(span -> "id as hex [" + span + "]").collect( - joining("\n"))); + log.info("Difference between parent ids and span ids " + difference.stream() + .map(span -> "id as hex [" + span + "]").collect(joining("\n"))); assertThat(spanIds).containsAll(parentSpanIds); } + } // Don't use @SpringBootApplication because we don't want to component scan @@ -210,6 +215,7 @@ class SampleZuulProxyApplication { Sampler alwaysSampler() { return Sampler.ALWAYS_SAMPLE; } + } class MyRouteLocator extends DiscoveryClientRouteLocator { @@ -218,6 +224,7 @@ class MyRouteLocator extends DiscoveryClientRouteLocator { ZuulProperties properties) { super(servletPath, discovery, properties); } + } // Load balancer with fixed server list for "simple" pointing to localhost @@ -231,4 +238,5 @@ class SimpleRibbonClientConfiguration { public ServerList ribbonServerList() { return new StaticServerList<>(new Server("localhost", this.port)); } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/issues/issue634/Issue634Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/issues/issue634/Issue634Tests.java index 8ddf50545..19e80b7d8 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/issues/issue634/Issue634Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/issues/issue634/Issue634Tests.java @@ -42,25 +42,29 @@ import com.netflix.zuul.ZuulFilter; import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringRunner.class) -@SpringBootTest(classes = TestZuulApplication.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - properties = {"feign.hystrix.enabled=false", - "zuul.routes.dp.path:/display/**", - "zuul.routes.dp.path.url: http://localhost:9987/unknown"}) +@SpringBootTest(classes = TestZuulApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { + "feign.hystrix.enabled=false", "zuul.routes.dp.path:/display/**", + "zuul.routes.dp.path.url: http://localhost:9987/unknown" }) @DirtiesContext public class Issue634Tests { - @LocalServerPort int port; - @Autowired HttpTracing tracer; - @Autowired TraceCheckingSpanFilter filter; - @Autowired ArrayListSpanReporter reporter; + @LocalServerPort + int port; + + @Autowired + HttpTracing tracer; + + @Autowired + TraceCheckingSpanFilter filter; + + @Autowired + ArrayListSpanReporter reporter; @Test public void should_reuse_custom_feign_client() { for (int i = 0; i < 15; i++) { - new TestRestTemplate() - .getForEntity("http://localhost:" + this.port + "/display/ddd", - String.class); + new TestRestTemplate().getForEntity( + "http://localhost:" + this.port + "/display/ddd", String.class); then(this.tracer.tracing().tracer().currentSpan()).isNull(); } @@ -69,6 +73,7 @@ public class Issue634Tests { .describedAs("trace id should not be reused from thread").hasSize(1); then(this.reporter.getSpans()).isNotEmpty(); } + } @EnableZuulProxy @@ -76,15 +81,18 @@ public class Issue634Tests { @Configuration class TestZuulApplication { - @Bean TraceCheckingSpanFilter traceCheckingSpanFilter(Tracing tracer) { + @Bean + TraceCheckingSpanFilter traceCheckingSpanFilter(Tracing tracer) { return new TraceCheckingSpanFilter(tracer); } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean ArrayListSpanReporter reporter() { + @Bean + ArrayListSpanReporter reporter() { return new ArrayListSpanReporter(); } @@ -93,28 +101,34 @@ class TestZuulApplication { class TraceCheckingSpanFilter extends ZuulFilter { private final Tracing tracer; + final Map counter = new ConcurrentHashMap<>(); TraceCheckingSpanFilter(Tracing tracer) { this.tracer = tracer; } - @Override public String filterType() { + @Override + public String filterType() { return "post"; } - @Override public int filterOrder() { + @Override + public int filterOrder() { return -1; } - @Override public boolean shouldFilter() { + @Override + public boolean shouldFilter() { return true; } - @Override public Object run() { + @Override + public Object run() { long trace = this.tracer.tracer().currentSpan().context().traceId(); Integer integer = this.counter.getOrDefault(trace, 0); counter.put(trace, integer + 1); return null; } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/Slf4JSpanLoggerTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/Slf4JSpanLoggerTest.java index 515bf67f0..5c0a9f2b4 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/Slf4JSpanLoggerTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/Slf4JSpanLoggerTest.java @@ -37,20 +37,21 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Marcin Grzejszczak */ @RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { - "spring.sleuth.baggage-keys=my-baggage", - "spring.sleuth.log.slf4j.whitelisted-mdc-keys=my-baggage" - }) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = { + "spring.sleuth.baggage-keys=my-baggage", + "spring.sleuth.log.slf4j.whitelisted-mdc-keys=my-baggage" }) @SpringBootConfiguration @EnableAutoConfiguration public class Slf4JSpanLoggerTest { - @Autowired Tracer tracer; - @Autowired Slf4jScopeDecorator slf4jScopeDecorator; + @Autowired + Tracer tracer; + + @Autowired + Slf4jScopeDecorator slf4jScopeDecorator; Span span; - + @Before @After public void setup() { @@ -60,9 +61,11 @@ public class Slf4JSpanLoggerTest { @Test public void should_set_entries_to_mdc_from_span() throws Exception { - Scope scope = this.slf4jScopeDecorator.decorateScope(this.span.context(), () -> { }); + Scope scope = this.slf4jScopeDecorator.decorateScope(this.span.context(), () -> { + }); - assertThat(MDC.get("X-B3-TraceId")).isEqualTo(this.span.context().traceIdString()); + assertThat(MDC.get("X-B3-TraceId")) + .isEqualTo(this.span.context().traceIdString()); assertThat(MDC.get("traceId")).isEqualTo(this.span.context().traceIdString()); scope.close(); @@ -74,7 +77,8 @@ public class Slf4JSpanLoggerTest { @Test public void should_set_entries_to_mdc_from_span_with_baggage() throws Exception { ExtraFieldPropagation.set(this.span.context(), "my-baggage", "my-value"); - Scope scope = this.slf4jScopeDecorator.decorateScope(this.span.context(), () -> { }); + Scope scope = this.slf4jScopeDecorator.decorateScope(this.span.context(), () -> { + }); assertThat(MDC.get("my-baggage")).isEqualTo("my-value"); @@ -88,7 +92,8 @@ public class Slf4JSpanLoggerTest { MDC.put("X-B3-TraceId", "A"); MDC.put("traceId", "A"); - Scope scope = this.slf4jScopeDecorator.decorateScope(null, () -> { }); + Scope scope = this.slf4jScopeDecorator.decorateScope(null, () -> { + }); assertThat(MDC.get("X-B3-TraceId")).isNullOrEmpty(); assertThat(MDC.get("traceId")).isNullOrEmpty(); @@ -98,4 +103,5 @@ public class Slf4JSpanLoggerTest { assertThat(MDC.get("X-B3-TraceId")).isEqualTo("A"); assertThat(MDC.get("traceId")).isEqualTo("A"); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/ProbabilityBasedSamplerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/ProbabilityBasedSamplerTests.java index 31ffb2c55..6896a0fa1 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/ProbabilityBasedSamplerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/ProbabilityBasedSamplerTests.java @@ -27,8 +27,9 @@ import static org.assertj.core.api.BDDAssertions.then; * @author Marcin Grzejszczak */ public class ProbabilityBasedSamplerTests { - + SamplerProperties samplerConfiguration = new SamplerProperties(); + private static Random RANDOM = new Random(); @Test @@ -36,8 +37,8 @@ public class ProbabilityBasedSamplerTests { this.samplerConfiguration.setProbability(1f); for (int i = 0; i < 10; i++) { - then(new ProbabilityBasedSampler(this.samplerConfiguration).isSampled(RANDOM.nextLong())) - .isTrue(); + then(new ProbabilityBasedSampler(this.samplerConfiguration) + .isSampled(RANDOM.nextLong())).isTrue(); } } @@ -48,8 +49,8 @@ public class ProbabilityBasedSamplerTests { this.samplerConfiguration.setProbability(0f); for (int i = 0; i < 10; i++) { - then(new ProbabilityBasedSampler(this.samplerConfiguration).isSampled(RANDOM.nextLong())) - .isFalse(); + then(new ProbabilityBasedSampler(this.samplerConfiguration) + .isSampled(RANDOM.nextLong())).isFalse(); } } @@ -65,7 +66,8 @@ public class ProbabilityBasedSamplerTests { } @Test - public void should_pass_given_percent_of_samples_with_fractional_element() throws Exception { + public void should_pass_given_percent_of_samples_with_fractional_element() + throws Exception { int numberOfIterations = 1000; float probability = 0.35f; this.samplerConfiguration.setProbability(probability); @@ -85,4 +87,5 @@ public class ProbabilityBasedSamplerTests { } return passedCounter; } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/util/SpanNameUtilTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/util/SpanNameUtilTests.java index 649f130e3..e85d87c26 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/util/SpanNameUtilTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/util/SpanNameUtilTests.java @@ -35,8 +35,7 @@ public class SpanNameUtilTests { @Test public void should_not_shorten_a_name_that_is_below_max_threshold() throws Exception { - BDDAssertions.then(SpanNameUtil.shorten("someName")) - .isEqualTo("someName"); + BDDAssertions.then(SpanNameUtil.shorten("someName")).isEqualTo("someName"); } @Test @@ -53,4 +52,5 @@ public class SpanNameUtilTests { BDDAssertions.then(SpanNameUtil.shorten(sb.toString()).length()) .isEqualTo(SpanNameUtil.MAX_NAME_LENGTH); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/util/SpanUtil.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/util/SpanUtil.java index bb03fd307..7f3d50a66 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/util/SpanUtil.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/util/SpanUtil.java @@ -33,14 +33,14 @@ public class SpanUtil { /** Inspired by {@code okio.Buffer.writeLong} */ static void writeHexLong(char[] data, int pos, long v) { - writeHexByte(data, pos + 0, (byte) ((v >>> 56L) & 0xff)); - writeHexByte(data, pos + 2, (byte) ((v >>> 48L) & 0xff)); - writeHexByte(data, pos + 4, (byte) ((v >>> 40L) & 0xff)); - writeHexByte(data, pos + 6, (byte) ((v >>> 32L) & 0xff)); - writeHexByte(data, pos + 8, (byte) ((v >>> 24L) & 0xff)); + writeHexByte(data, pos + 0, (byte) ((v >>> 56L) & 0xff)); + writeHexByte(data, pos + 2, (byte) ((v >>> 48L) & 0xff)); + writeHexByte(data, pos + 4, (byte) ((v >>> 40L) & 0xff)); + writeHexByte(data, pos + 6, (byte) ((v >>> 32L) & 0xff)); + writeHexByte(data, pos + 8, (byte) ((v >>> 24L) & 0xff)); writeHexByte(data, pos + 10, (byte) ((v >>> 16L) & 0xff)); writeHexByte(data, pos + 12, (byte) ((v >>> 8L) & 0xff)); - writeHexByte(data, pos + 14, (byte) (v & 0xff)); + writeHexByte(data, pos + 14, (byte) (v & 0xff)); } static void writeHexByte(char[] data, int pos, byte b) { @@ -48,6 +48,7 @@ public class SpanUtil { data[pos + 1] = HEX_DIGITS[b & 0xf]; } - static final char[] HEX_DIGITS = - {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' }; + } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/src/main/java/sample/SampleController.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/src/main/java/sample/SampleController.java index fb3404244..8e28f8733 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/src/main/java/sample/SampleController.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-feign/src/main/java/sample/SampleController.java @@ -32,6 +32,7 @@ import org.springframework.web.bind.annotation.RestController; public class SampleController { private final Zipkin zipkin; + private final Random random = new Random(); @Autowired @@ -56,9 +57,11 @@ public class SampleController { @FeignClient("zipkin") interface Zipkin { + @RequestMapping(value = "/call", method = RequestMethod.GET) String call(); @RequestMapping(value = "/hi2", method = RequestMethod.GET) String hi2(); + } \ No newline at end of file diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java index 2c2d3eb46..05a75c961 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java @@ -31,6 +31,7 @@ public class SampleBackground { @Autowired private Tracer tracer; + private Random random = new Random(); @Async diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleRequestResponse.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleRequestResponse.java index 1ac052adc..a11626c30 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleRequestResponse.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleRequestResponse.java @@ -26,7 +26,7 @@ import org.springframework.integration.annotation.MessagingGateway; @MessagingGateway public interface SampleRequestResponse { - @Gateway(requestChannel="xform") + @Gateway(requestChannel = "xform") String send(String input); } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleService.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleService.java index 35d633d2b..c4c5b6b4d 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleService.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleService.java @@ -30,20 +30,27 @@ import org.springframework.web.client.RestTemplate; * @author Dave Syer * */ -@MessageEndpoint public class SampleService implements - ApplicationListener { +@MessageEndpoint +public class SampleService + implements ApplicationListener { + private static final Log log = LogFactory.getLog(SampleService.class); - @Autowired private RestTemplate restTemplate; + @Autowired + private RestTemplate restTemplate; + private int port; - @ServiceActivator(inputChannel="messages") + @ServiceActivator(inputChannel = "messages") public void log(Message message) { log.info("Received: " + message); - this.restTemplate.getForObject("http://localhost:" + this.port + "/foo", String.class); + this.restTemplate.getForObject("http://localhost:" + this.port + "/foo", + String.class); } - @Override public void onApplicationEvent(ServletWebServerInitializedEvent event) { + @Override + public void onApplicationEvent(ServletWebServerInitializedEvent event) { this.port = event.getSource().getPort(); } + } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleSink.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleSink.java index d9abf93e3..7a99b309f 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleSink.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleSink.java @@ -26,7 +26,7 @@ import org.springframework.integration.annotation.MessagingGateway; @MessagingGateway public interface SampleSink { - @Gateway(requestChannel="messages") + @Gateway(requestChannel = "messages") void send(String message); } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleTransformer.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleTransformer.java index 7753bf199..44816ac4e 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleTransformer.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleTransformer.java @@ -35,7 +35,7 @@ public class SampleTransformer { @Autowired SampleBackground background; - @ServiceActivator(inputChannel="xform") + @ServiceActivator(inputChannel = "xform") public String log(Message message) throws InterruptedException { log.info("Received: " + message); this.background.background(); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java index edb21e68d..2ec3b8c4f 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java @@ -42,16 +42,19 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = { IntegrationSpanCollectorConfig.class, SampleMessagingApplication.class }, - webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@SpringBootTest(classes = { IntegrationSpanCollectorConfig.class, + SampleMessagingApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @TestPropertySource(properties = { "sample.zipkin.enabled=true", "spring.sleuth.http.legacy.enabled=true" }) @DirtiesContext public class MessagingApplicationTests extends AbstractIntegrationTest { private static int port = 3381; + private static String sampleAppUrl = "http://localhost:" + port; - @Autowired IntegrationTestZipkinSpanReporter integrationTestSpanCollector; + + @Autowired + IntegrationTestZipkinSpanReporter integrationTestSpanCollector; @After public void cleanup() { @@ -62,13 +65,12 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { public void should_have_passed_trace_id_when_message_is_about_to_be_sent() { long traceId = new Random().nextLong(); - await().atMost(15, SECONDS).untilAsserted(() -> - httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/", traceId).run() - ); + await().atMost(15, SECONDS) + .untilAsserted(() -> httpMessageWithTraceIdInHeadersIsSuccessfullySent( + sampleAppUrl + "/", traceId).run()); - await().atMost(15, SECONDS).untilAsserted(() -> - thenAllSpansHaveTraceIdEqualTo(traceId) - ); + await().atMost(15, SECONDS) + .untilAsserted(() -> thenAllSpansHaveTraceIdEqualTo(traceId)); } @Test @@ -76,9 +78,9 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { long traceId = new Random().nextLong(); long spanId = new Random().nextLong(); - await().atMost(15, SECONDS).untilAsserted(() -> - httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/", traceId, spanId).run() - ); + await().atMost(15, SECONDS) + .untilAsserted(() -> httpMessageWithTraceIdInHeadersIsSuccessfullySent( + sampleAppUrl + "/", traceId, spanId).run()); await().atMost(15, SECONDS).untilAsserted(() -> { thenAllSpansHaveTraceIdEqualTo(traceId); @@ -90,9 +92,9 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { public void should_have_passed_trace_id_with_annotations_in_async_thread_when_message_is_about_to_be_sent() { long traceId = new Random().nextLong(); - await().atMost(15, SECONDS).untilAsserted(() -> - httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/xform", traceId).run() - ); + await().atMost(15, SECONDS) + .untilAsserted(() -> httpMessageWithTraceIdInHeadersIsSuccessfullySent( + sampleAppUrl + "/xform", traceId).run()); await().atMost(15, SECONDS).untilAsserted(() -> { thenAllSpansHaveTraceIdEqualTo(traceId); @@ -101,24 +103,22 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { } private void thenThereIsAtLeastOneTagWithKey(String key) { - then(this.integrationTestSpanCollector.hashedSpans.stream() - .map(Span::tags) - .flatMap(m -> m.keySet().stream()) - .anyMatch(b -> b.equals(key))).isTrue(); + then(this.integrationTestSpanCollector.hashedSpans.stream().map(Span::tags) + .flatMap(m -> m.keySet().stream()).anyMatch(b -> b.equals(key))).isTrue(); } private void thenAllSpansHaveTraceIdEqualTo(long traceId) { String traceIdHex = Long.toHexString(traceId); - log.info("Stored spans: [\n" + this.integrationTestSpanCollector.hashedSpans - .stream() - .map(Span::toString) - .collect(Collectors.joining("\n")) + "\n]"); - then(this.integrationTestSpanCollector.hashedSpans - .stream() + log.info( + "Stored spans: [\n" + + this.integrationTestSpanCollector.hashedSpans.stream() + .map(Span::toString).collect(Collectors.joining("\n")) + + "\n]"); + then(this.integrationTestSpanCollector.hashedSpans.stream() .filter(span -> !span.traceId().equals(SpanUtil.idToHex(traceId))) .collect(Collectors.toList())) - .describedAs("All spans have same trace id [" + traceIdHex + "]") - .isEmpty(); + .describedAs("All spans have same trace id [" + traceIdHex + "]") + .isEmpty(); } private void thenTheSpansHaveProperParentStructure() { @@ -127,40 +127,44 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { Optional eventSentSpan = findSpanWithKind(Span.Kind.SERVER); Optional producerSpan = findSpanWithKind(Span.Kind.PRODUCER); Optional lastHttpSpansParent = findLastHttpSpansParent(); - // "http:/parent/" -> "message:messages" -> "http:/foo" (CS + CR) -> "http:/foo" (SS) - thenAllSpansArePresent(firstHttpSpan, eventSpans, lastHttpSpansParent, eventSentSpan, producerSpan); - then(this.integrationTestSpanCollector.hashedSpans).as("There were 6 spans").hasSize(6); + // "http:/parent/" -> "message:messages" -> "http:/foo" (CS + CR) -> "http:/foo" + // (SS) + thenAllSpansArePresent(firstHttpSpan, eventSpans, lastHttpSpansParent, + eventSentSpan, producerSpan); + then(this.integrationTestSpanCollector.hashedSpans).as("There were 6 spans") + .hasSize(6); log.info("Checking the parent child structure"); - List> parentChild = this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> span.parentId() != null) - .map(span -> this.integrationTestSpanCollector.hashedSpans.stream().filter(span1 -> span1.id().equals(span.parentId())).findAny() - ).collect(Collectors.toList()); + List> parentChild = this.integrationTestSpanCollector.hashedSpans + .stream().filter(span -> span.parentId() != null) + .map(span -> this.integrationTestSpanCollector.hashedSpans.stream() + .filter(span1 -> span1.id().equals(span.parentId())).findAny()) + .collect(Collectors.toList()); log.info("List of parents and children " + parentChild); then(parentChild.stream().allMatch(Optional::isPresent)).isTrue(); } private Optional findLastHttpSpansParent() { return this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> "http:/".equals(span.name()) && span.kind() != null).findFirst(); + .filter(span -> "http:/".equals(span.name()) && span.kind() != null) + .findFirst(); } private Optional findSpanWithKind(Span.Kind kind) { return this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> kind.equals(span.kind())) - .findFirst(); + .filter(span -> kind.equals(span.kind())).findFirst(); } private List findAllEventRelatedSpans() { return this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> "send".equals(span.name()) && span.parentId() != null).collect( - Collectors.toList()); + .filter(span -> "send".equals(span.name()) && span.parentId() != null) + .collect(Collectors.toList()); } private Optional findFirstHttpRequestSpan() { return this.integrationTestSpanCollector.hashedSpans.stream() // home is the name of the method - .filter(span -> span.tags().values().stream() - .anyMatch("home"::equals)).findFirst(); + .filter(span -> span.tags().values().stream().anyMatch("home"::equals)) + .findFirst(); } private void thenAllSpansArePresent(Optional firstHttpSpan, @@ -183,13 +187,17 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { @Configuration public static class IntegrationSpanCollectorConfig { + @Bean Reporter integrationTestZipkinSpanReporter() { return new IntegrationTestZipkinSpanReporter(); } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } + } + } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleController.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleController.java index dd714c9eb..82cfd5dfd 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleController.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleController.java @@ -28,10 +28,11 @@ import org.springframework.web.client.RestTemplate; * @author Dave Syer */ @RestController -public class SampleController { +public class SampleController { @Autowired private RestTemplate restTemplate; + private Random random = new Random(); @RequestMapping("/") diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java index b16a8a52c..8dd2dd4df 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java @@ -30,22 +30,28 @@ import static java.util.concurrent.TimeUnit.SECONDS; */ public abstract class AbstractIntegrationTest { - protected static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + protected static final Log log = LogFactory + .getLog(MethodHandles.lookup().lookupClass()); protected static final int POLL_INTERVAL = 1; + protected static final int TIMEOUT = 20; + protected final RestTemplate restTemplate = new AssertingRestTemplate(); - - protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, long traceId) { + protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, + long traceId) { return new RequestSendingRunnable(this.restTemplate, endpoint, traceId, traceId); } - protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, long traceId, Long spanId) { + protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, + long traceId, Long spanId) { return new RequestSendingRunnable(this.restTemplate, endpoint, traceId, spanId); } public static ConditionFactory await() { - return Awaitility.await().pollInterval(POLL_INTERVAL, SECONDS).atMost(TIMEOUT, SECONDS); + return Awaitility.await().pollInterval(POLL_INTERVAL, SECONDS).atMost(TIMEOUT, + SECONDS); } + } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AssertingRestTemplate.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AssertingRestTemplate.java index 4e88ff50c..e1d74c00b 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AssertingRestTemplate.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AssertingRestTemplate.java @@ -30,7 +30,8 @@ import org.springframework.web.client.RestTemplate; /** * - * RestTemplate that logs erroneous responses and throws AssertionsError on any connection issues + * RestTemplate that logs erroneous responses and throws AssertionsError on any connection + * issues * * @author Marcin Grzejszczak */ @@ -43,19 +44,24 @@ public class AssertingRestTemplate extends RestTemplate { @Override public void handleError(ClientHttpResponse response) throws IOException { if (hasError(response)) { - log.error("Response has status code [" + response.getStatusCode() + "] and text [" + response.getStatusText() + "])"); + log.error("Response has status code [" + response.getStatusCode() + + "] and text [" + response.getStatusText() + "])"); } } }); } @Override - protected T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor) throws RestClientException { + protected T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, + ResponseExtractor responseExtractor) throws RestClientException { try { return super.doExecute(url, method, requestCallback, responseExtractor); - } catch (Exception e) { - log.error("Exception occurred while sending the message to uri [" + url +"]. Exception [" + e.getCause() + "]"); + } + catch (Exception e) { + log.error("Exception occurred while sending the message to uri [" + url + + "]. Exception [" + e.getCause() + "]"); throw new AssertionError(e); } } + } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java index 98c3dbf0a..c358a1e64 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java @@ -30,21 +30,26 @@ import org.springframework.web.client.RestTemplate; import static org.assertj.core.api.BDDAssertions.then; /** - * Runnable that will send a request via the provide rest template to the - * given url. It will also append the provided TraceID as the request's header + * Runnable that will send a request via the provide rest template to the given url. It + * will also append the provided TraceID as the request's header * * @author Marcin Grzejszczak */ public class RequestSendingRunnable implements Runnable { + static final String TRACE_ID_NAME = "X-B3-TraceId"; static final String SPAN_ID_NAME = "X-B3-SpanId"; private static final Log log = LogFactory.getLog(RequestSendingRunnable.class); private final RestTemplate restTemplate; + private final String url; + private final long traceId; + private final Random random = new Random(); + private final long spanId; public RequestSendingRunnable(RestTemplate restTemplate, String url, long traceId, @@ -57,20 +62,24 @@ public class RequestSendingRunnable implements Runnable { @Override public void run() { - log.info(String.format("Sending the request to url [%s] with trace id in headers [%d]", this.url, this.traceId)); - ResponseEntity responseEntity = - this.restTemplate.exchange(requestWithTraceId(), String.class); + log.info(String.format( + "Sending the request to url [%s] with trace id in headers [%d]", this.url, + this.traceId)); + ResponseEntity responseEntity = this.restTemplate + .exchange(requestWithTraceId(), String.class); then(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); log.info(String.format("Received the following response [%s]", responseEntity)); } private RequestEntity requestWithTraceId() { HttpHeaders headers = new HttpHeaders(); - headers.add(TRACE_ID_NAME,SpanUtil.idToHex(this.traceId)); + headers.add(TRACE_ID_NAME, SpanUtil.idToHex(this.traceId)); headers.add(SPAN_ID_NAME, SpanUtil.idToHex(this.spanId)); URI uri = URI.create(this.url); - RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, uri); + RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, + uri); log.info("Request [" + requestEntity + "] is ready"); return requestEntity; } + } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/SpanUtil.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/SpanUtil.java index 343c42f0a..e011d2995 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/SpanUtil.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/SpanUtil.java @@ -29,14 +29,14 @@ public class SpanUtil { /** Inspired by {@code okio.Buffer.writeLong} */ static void writeHexLong(char[] data, int pos, long v) { - writeHexByte(data, pos + 0, (byte) ((v >>> 56L) & 0xff)); - writeHexByte(data, pos + 2, (byte) ((v >>> 48L) & 0xff)); - writeHexByte(data, pos + 4, (byte) ((v >>> 40L) & 0xff)); - writeHexByte(data, pos + 6, (byte) ((v >>> 32L) & 0xff)); - writeHexByte(data, pos + 8, (byte) ((v >>> 24L) & 0xff)); + writeHexByte(data, pos + 0, (byte) ((v >>> 56L) & 0xff)); + writeHexByte(data, pos + 2, (byte) ((v >>> 48L) & 0xff)); + writeHexByte(data, pos + 4, (byte) ((v >>> 40L) & 0xff)); + writeHexByte(data, pos + 6, (byte) ((v >>> 32L) & 0xff)); + writeHexByte(data, pos + 8, (byte) ((v >>> 24L) & 0xff)); writeHexByte(data, pos + 10, (byte) ((v >>> 16L) & 0xff)); writeHexByte(data, pos + 12, (byte) ((v >>> 8L) & 0xff)); - writeHexByte(data, pos + 14, (byte) (v & 0xff)); + writeHexByte(data, pos + 14, (byte) (v & 0xff)); } static void writeHexByte(char[] data, int pos, byte b) { @@ -44,6 +44,7 @@ public class SpanUtil { data[pos + 1] = HEX_DIGITS[b & 0xf]; } - static final char[] HEX_DIGITS = - {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' }; + } \ No newline at end of file diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-websocket/src/main/java/sample/SampleWebsocketApplication.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-websocket/src/main/java/sample/SampleWebsocketApplication.java index 0b8d487af..ef505e69a 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-websocket/src/main/java/sample/SampleWebsocketApplication.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-websocket/src/main/java/sample/SampleWebsocketApplication.java @@ -41,4 +41,5 @@ public class SampleWebsocketApplication extends AbstractWebSocketMessageBrokerCo public static void main(String[] args) { SpringApplication.run(SampleWebsocketApplication.class, args); } + } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleBackground.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleBackground.java index 2c2d3eb46..05a75c961 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleBackground.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleBackground.java @@ -31,6 +31,7 @@ public class SampleBackground { @Autowired private Tracer tracer; + private Random random = new Random(); @Async diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleController.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleController.java index c0d54d54d..e87b3debe 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleController.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleController.java @@ -34,26 +34,30 @@ import org.springframework.web.client.RestTemplate; * @author Spencer Gibb */ @RestController -public class SampleController implements -ApplicationListener { +public class SampleController + implements ApplicationListener { private static final Log log = LogFactory.getLog(SampleController.class); @Autowired private RestTemplate restTemplate; + @Autowired private Tracer tracer; + @Autowired private SampleBackground controller; + private Random random = new Random(); + private int port; @RequestMapping("/") public String hi() throws InterruptedException { Thread.sleep(this.random.nextInt(1000)); log.info("Home page"); - String s = this.restTemplate.getForObject("http://localhost:" + this.port - + "/hi2", String.class); + String s = this.restTemplate + .getForObject("http://localhost:" + this.port + "/hi2", String.class); return "hi/" + s; } @@ -95,8 +99,8 @@ ApplicationListener { Thread.sleep(millis); this.tracer.currentSpan().tag("random-sleep-millis", String.valueOf(millis)); - String s = this.restTemplate.getForObject("http://localhost:" + this.port - + "/call", String.class); + String s = this.restTemplate + .getForObject("http://localhost:" + this.port + "/call", String.class); span.finish(); return "traced/" + s; } @@ -107,8 +111,8 @@ ApplicationListener { log.info(String.format("Sleeping for [%d] millis", millis)); Thread.sleep(millis); this.tracer.currentSpan().tag("random-sleep-millis", String.valueOf(millis)); - String s = this.restTemplate.getForObject("http://localhost:" + this.port - + "/call", String.class); + String s = this.restTemplate + .getForObject("http://localhost:" + this.port + "/call", String.class); return "start/" + s; } @@ -116,4 +120,5 @@ ApplicationListener { public void onApplicationEvent(ServletWebServerInitializedEvent event) { this.port = event.getSource().getPort(); } + } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinTests.java index 43b081c00..cec5c751a 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinTests.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinTests.java @@ -50,17 +50,23 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(classes = { WaitUntilZipkinIsUpConfig.class, SampleZipkinApplication.class }, - webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@TestPropertySource(properties = {"sample.zipkin.enabled=true"}) +@SpringBootTest(classes = { WaitUntilZipkinIsUpConfig.class, + SampleZipkinApplication.class }, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@TestPropertySource(properties = { "sample.zipkin.enabled=true" }) public class ZipkinTests extends AbstractIntegrationTest { - @ClassRule public static final MockWebServer zipkin = new MockWebServer(); + + @ClassRule + public static final MockWebServer zipkin = new MockWebServer(); private static final String APP_NAME = "testsleuthzipkin"; + @Value("${local.server.port}") private int port = 3380; + private String sampleAppUrl = "http://localhost:" + this.port; - @Autowired ZipkinProperties zipkinProperties; + + @Autowired + ZipkinProperties zipkinProperties; @Test public void should_propagate_spans_to_zipkin() throws Exception { @@ -68,15 +74,14 @@ public class ZipkinTests extends AbstractIntegrationTest { long traceId = new Random().nextLong(); - await().atMost(10, SECONDS).untilAsserted(() -> - httpMessageWithTraceIdInHeadersIsSuccessfullySent( - this.sampleAppUrl + "/hi2", traceId).run() - ); + await().atMost(10, SECONDS) + .untilAsserted(() -> httpMessageWithTraceIdInHeadersIsSuccessfullySent( + this.sampleAppUrl + "/hi2", traceId).run()); spansSentToZipkin(zipkin, traceId); } - String getAppName() { + String getAppName() { return APP_NAME; } @@ -91,21 +96,27 @@ public class ZipkinTests extends AbstractIntegrationTest { return zipkinProperties; } - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } + } void spansSentToZipkin(MockWebServer zipkin, long traceId) throws InterruptedException { RecordedRequest request = zipkin.takeRequest(); - List spans = SpanBytesDecoder.JSON_V2.decodeList(request.getBody().readByteArray()); + List spans = SpanBytesDecoder.JSON_V2 + .decodeList(request.getBody().readByteArray()); List traceIdsNotFoundInZipkin = traceIdsNotFoundInZipkin(spans, traceId); List serviceNamesNotFoundInZipkin = serviceNamesNotFoundInZipkin(spans); List tagsNotFoundInZipkin = hasRequiredTag(spans); - log.info(String.format("The following trace IDs were not found in Zipkin [%s]", traceIdsNotFoundInZipkin)); - log.info(String.format("The following services were not found in Zipkin [%s]", serviceNamesNotFoundInZipkin)); - log.info(String.format("The following tags were not found in Zipkin [%s]", tagsNotFoundInZipkin)); + log.info(String.format("The following trace IDs were not found in Zipkin [%s]", + traceIdsNotFoundInZipkin)); + log.info(String.format("The following services were not found in Zipkin [%s]", + serviceNamesNotFoundInZipkin)); + log.info(String.format("The following tags were not found in Zipkin [%s]", + tagsNotFoundInZipkin)); then(traceIdsNotFoundInZipkin).isEmpty(); then(serviceNamesNotFoundInZipkin).isEmpty(); then(tagsNotFoundInZipkin).isEmpty(); @@ -114,24 +125,17 @@ public class ZipkinTests extends AbstractIntegrationTest { List traceIdsNotFoundInZipkin(List spans, long traceId) { String traceIdString = SpanUtil.idToHex(traceId); - Optional traceIds = spans.stream() - .map(Span::traceId) - .filter(traceIdString::equals) - .findFirst(); - return traceIds.isPresent() ? Collections.emptyList() : Collections.singletonList(traceIdString); + Optional traceIds = spans.stream().map(Span::traceId) + .filter(traceIdString::equals).findFirst(); + return traceIds.isPresent() ? Collections.emptyList() + : Collections.singletonList(traceIdString); } List serviceNamesNotFoundInZipkin(List spans) { - List localServiceNames = spans.stream() - .map(Span::localServiceName) - .filter(Objects::nonNull) - .distinct() - .collect(Collectors.toList()); - List remoteServiceNames = spans.stream() - .map(Span::remoteServiceName) - .filter(Objects::nonNull) - .distinct() - .collect(Collectors.toList()); + List localServiceNames = spans.stream().map(Span::localServiceName) + .filter(Objects::nonNull).distinct().collect(Collectors.toList()); + List remoteServiceNames = spans.stream().map(Span::remoteServiceName) + .filter(Objects::nonNull).distinct().collect(Collectors.toList()); List names = new ArrayList<>(); names.addAll(localServiceNames); names.addAll(remoteServiceNames); @@ -141,13 +145,14 @@ public class ZipkinTests extends AbstractIntegrationTest { List hasRequiredTag(List spans) { String key = getRequiredTagKey(); Optional keys = spans.stream() - .flatMap(span -> span.tags().keySet().stream()) - .filter(key::equals) + .flatMap(span -> span.tags().keySet().stream()).filter(key::equals) .findFirst(); - return keys.isPresent() ? Collections.emptyList() : Collections.singletonList(key); + return keys.isPresent() ? Collections.emptyList() + : Collections.singletonList(key); } String getRequiredTagKey() { return "random-sleep-millis"; } + } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleBackground.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleBackground.java index ee0af331a..9f3893eed 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleBackground.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleBackground.java @@ -30,10 +30,12 @@ import org.springframework.stereotype.Component; */ @Component public class SampleBackground { + private static final Log log = LogFactory.getLog(SampleBackground.class); @Autowired private Tracer tracer; + private Random random = new Random(); @Async diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleController.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleController.java index 2948441c3..fc568b03e 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleController.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleController.java @@ -35,16 +35,21 @@ import org.springframework.web.client.RestTemplate; */ @RestController public class SampleController - implements ApplicationListener { + implements ApplicationListener { + private static final Log log = LogFactory.getLog(SampleController.class); + @Autowired private RestTemplate restTemplate; + @Autowired private Tracer tracer; + @Autowired private SampleBackground controller; private final Random random = new Random(); + private int port; @RequestMapping("/") @@ -121,4 +126,5 @@ public class SampleController public void onApplicationEvent(ServletWebServerInitializedEvent event) { this.port = event.getSource().getPort(); } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/DefaultEndpointLocator.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/DefaultEndpointLocator.java index 7c5670862..7cafade9b 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/DefaultEndpointLocator.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/DefaultEndpointLocator.java @@ -35,9 +35,9 @@ import zipkin2.Endpoint; * {@link EndpointLocator} implementation that: * *
      - *
    • serviceName - from {@link ServerProperties} or {@link Registration}
    • - *
    • ip - from {@link ServerProperties}
    • - *
    • port - from lazily assigned port or {@link ServerProperties}
    • + *
    • serviceName - from {@link ServerProperties} or {@link Registration}
    • + *
    • ip - from {@link ServerProperties}
    • + *
    • port - from lazily assigned port or {@link ServerProperties}
    • *
    * * You can override the name using {@link ZipkinProperties.Service#setName(String)} @@ -48,18 +48,26 @@ import zipkin2.Endpoint; public class DefaultEndpointLocator implements EndpointLocator, ApplicationListener { - private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()); + private static final Log log = LogFactory + .getLog(MethodHandles.lookup().lookupClass()); + private static final String IP_ADDRESS_PROP_NAME = "spring.cloud.client.ipAddress"; private final Registration registration; + private final ServerProperties serverProperties; + private final Environment environment; + private final ZipkinProperties zipkinProperties; + private Integer port; + private InetAddress firstNonLoopbackAddress; - public DefaultEndpointLocator(Registration registration, ServerProperties serverProperties, - Environment environment, ZipkinProperties zipkinProperties, InetUtils inetUtils) { + public DefaultEndpointLocator(Registration registration, + ServerProperties serverProperties, Environment environment, + ZipkinProperties zipkinProperties, InetUtils inetUtils) { this.registration = registration; this.serverProperties = serverProperties; this.environment = environment; @@ -80,8 +88,7 @@ public class DefaultEndpointLocator implements EndpointLocator, if (log.isDebugEnabled()) { log.debug("Span will contain serviceName [" + serviceName + "]"); } - Endpoint.Builder builder = Endpoint.newBuilder() - .serviceName(serviceName) + Endpoint.Builder builder = Endpoint.newBuilder().serviceName(serviceName) .port(getPort()); return addAddress(builder).build(); } @@ -89,10 +96,12 @@ public class DefaultEndpointLocator implements EndpointLocator, private String getLocalServiceName() { if (StringUtils.hasText(this.zipkinProperties.getService().getName())) { return this.zipkinProperties.getService().getName(); - } else if (this.registration != null) { + } + else if (this.registration != null) { try { return this.registration.getServiceId(); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { log.warn("error getting service name from registration", e); } } @@ -105,11 +114,12 @@ public class DefaultEndpointLocator implements EndpointLocator, } private Integer getPort() { - if (this.port!=null) { + if (this.port != null) { return this.port; } Integer port; - if (this.serverProperties!=null && this.serverProperties.getPort() != null && this.serverProperties.getPort() > 0) { + if (this.serverProperties != null && this.serverProperties.getPort() != null + && this.serverProperties.getPort() > 0) { port = this.serverProperties.getPort(); } else { @@ -124,11 +134,13 @@ public class DefaultEndpointLocator implements EndpointLocator, return builder; } else if (this.environment.containsProperty(IP_ADDRESS_PROP_NAME) - && builder.parseIp(this.environment.getProperty(IP_ADDRESS_PROP_NAME, String.class))) { + && builder.parseIp(this.environment.getProperty(IP_ADDRESS_PROP_NAME, + String.class))) { return builder; } else { return builder.ip(this.firstNonLoopbackAddress); } } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/DefaultZipkinRestTemplateCustomizer.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/DefaultZipkinRestTemplateCustomizer.java index 9e5179c0d..fd3791b5c 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/DefaultZipkinRestTemplateCustomizer.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/DefaultZipkinRestTemplateCustomizer.java @@ -31,14 +31,13 @@ import org.springframework.web.client.RestTemplate; * {@link ZipkinProperties#compression} is enabled. * * @author Marcin Grzejszczak - * * @since 1.1.0 */ public class DefaultZipkinRestTemplateCustomizer implements ZipkinRestTemplateCustomizer { + private final ZipkinProperties zipkinProperties; - public DefaultZipkinRestTemplateCustomizer( - ZipkinProperties zipkinProperties) { + public DefaultZipkinRestTemplateCustomizer(ZipkinProperties zipkinProperties) { this.zipkinProperties = zipkinProperties; } @@ -51,8 +50,8 @@ public class DefaultZipkinRestTemplateCustomizer implements ZipkinRestTemplateCu private class GZipInterceptor implements ClientHttpRequestInterceptor { - public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws - IOException { + public ClientHttpResponse intercept(HttpRequest request, byte[] body, + ClientHttpRequestExecution execution) throws IOException { request.getHeaders().add("Content-Encoding", "gzip"); ByteArrayOutputStream gzipped = new ByteArrayOutputStream(); try (GZIPOutputStream compressor = new GZIPOutputStream(gzipped)) { @@ -60,5 +59,7 @@ public class DefaultZipkinRestTemplateCustomizer implements ZipkinRestTemplateCu } return execution.execute(request, gzipped.toByteArray()); } + } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfiguration.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfiguration.java index 68aede051..9a227a2d9 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfiguration.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfiguration.java @@ -49,23 +49,22 @@ import zipkin2.reporter.Sender; import java.util.concurrent.TimeUnit; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * enables reporting to Zipkin via HTTP. Has a default {@link Sampler} set as - * {@link ProbabilityBasedSampler}. + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} enables reporting to Zipkin via HTTP. Has a default {@link Sampler} + * set as {@link ProbabilityBasedSampler}. * - * The {@link ZipkinRestTemplateCustomizer} allows you to customize the {@link RestTemplate} - * that is used to send Spans to Zipkin. Its default implementation - {@link DefaultZipkinRestTemplateCustomizer} - * adds the GZip compression. + * The {@link ZipkinRestTemplateCustomizer} allows you to customize the + * {@link RestTemplate} that is used to send Spans to Zipkin. Its default implementation - + * {@link DefaultZipkinRestTemplateCustomizer} adds the GZip compression. * * @author Spencer Gibb * @since 1.0.0 - * * @see ProbabilityBasedSampler * @see ZipkinRestTemplateCustomizer * @see DefaultZipkinRestTemplateCustomizer */ @Configuration -@EnableConfigurationProperties({ZipkinProperties.class, SamplerProperties.class}) +@EnableConfigurationProperties({ ZipkinProperties.class, SamplerProperties.class }) @ConditionalOnProperty(value = "spring.zipkin.enabled", matchIfMissing = true) @AutoConfigureBefore(TraceAutoConfiguration.class) @AutoConfigureAfter(name = "org.springframework.cloud.autoconfigure.RefreshAutoConfiguration") @@ -73,22 +72,20 @@ import java.util.concurrent.TimeUnit; public class ZipkinAutoConfiguration { /** - * Accepts a sender so you can plug-in any standard one. Returns a Reporter so you can also - * replace with a standard one. + * Accepts a sender so you can plug-in any standard one. Returns a Reporter so you can + * also replace with a standard one. */ @Bean @ConditionalOnMissingBean - public Reporter reporter( - ReporterMetrics reporterMetrics, - ZipkinProperties zipkin, - Sender sender, - BytesEncoder spanBytesEncoder - ) { - return AsyncReporter.builder(sender) - .queuedMaxSpans(1000) // historical constraint. Note: AsyncReporter supports memory bounds + public Reporter reporter(ReporterMetrics reporterMetrics, + ZipkinProperties zipkin, Sender sender, BytesEncoder spanBytesEncoder) { + return AsyncReporter.builder(sender).queuedMaxSpans(1000) // historical + // constraint. Note: + // AsyncReporter + // supports memory + // bounds .messageTimeout(zipkin.getMessageTimeout(), TimeUnit.SECONDS) - .metrics(reporterMetrics) - .build(spanBytesEncoder); + .metrics(reporterMetrics).build(spanBytesEncoder); } @Bean @@ -99,7 +96,8 @@ public class ZipkinAutoConfiguration { @Bean @ConditionalOnMissingBean - public ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer(ZipkinProperties zipkinProperties) { + public ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer( + ZipkinProperties zipkinProperties) { return new DefaultZipkinRestTemplateCustomizer(zipkinProperties); } @@ -112,22 +110,26 @@ public class ZipkinAutoConfiguration { @Configuration @ConditionalOnBean(type = "org.springframework.cloud.context.scope.refresh.RefreshScope") protected static class RefreshScopedProbabilityBasedSamplerConfiguration { + @Bean @RefreshScope @ConditionalOnMissingBean public Sampler defaultTraceSampler(SamplerProperties config) { return new ProbabilityBasedSampler(config); } + } @Configuration @ConditionalOnMissingBean(type = "org.springframework.cloud.context.scope.refresh.RefreshScope") protected static class NonRefreshScopeProbabilityBasedSamplerConfiguration { + @Bean @ConditionalOnMissingBean public Sampler defaultTraceSampler(SamplerProperties config) { return new ProbabilityBasedSampler(config); } + } @Configuration @@ -135,13 +137,13 @@ public class ZipkinAutoConfiguration { @ConditionalOnProperty(value = "spring.zipkin.locator.discovery.enabled", havingValue = "false", matchIfMissing = true) protected static class DefaultEndpointLocatorConfiguration { - @Autowired(required=false) + @Autowired(required = false) private ServerProperties serverProperties; @Autowired private ZipkinProperties zipkinProperties; - @Autowired(required=false) + @Autowired(required = false) private InetUtils inetUtils; @Autowired @@ -149,8 +151,8 @@ public class ZipkinAutoConfiguration { @Bean public EndpointLocator zipkinEndpointLocator() { - return new DefaultEndpointLocator(null, this.serverProperties, this.environment, - this.zipkinProperties, this.inetUtils); + return new DefaultEndpointLocator(null, this.serverProperties, + this.environment, this.zipkinProperties, this.inetUtils); } } @@ -161,25 +163,27 @@ public class ZipkinAutoConfiguration { @ConditionalOnProperty(value = "spring.zipkin.locator.discovery.enabled", havingValue = "true") protected static class RegistrationEndpointLocatorConfiguration { - @Autowired(required=false) + @Autowired(required = false) private ServerProperties serverProperties; @Autowired private ZipkinProperties zipkinProperties; - @Autowired(required=false) + @Autowired(required = false) private InetUtils inetUtils; @Autowired private Environment environment; - @Autowired(required=false) + @Autowired(required = false) private Registration registration; @Bean public EndpointLocator zipkinEndpointLocator() { - return new DefaultEndpointLocator(this.registration, this.serverProperties, this.environment, - this.zipkinProperties, this.inetUtils); + return new DefaultEndpointLocator(this.registration, this.serverProperties, + this.environment, this.zipkinProperties, this.inetUtils); } + } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinLoadBalancer.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinLoadBalancer.java index 4cb734e0a..03f5fac9c 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinLoadBalancer.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinLoadBalancer.java @@ -28,8 +28,8 @@ public interface ZipkinLoadBalancer { /** * Returns a concrete {@link URI} of a Zipkin instance. - * * @return {@link URI} of the picked instance */ URI instance(); + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinProperties.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinProperties.java index 0988772f5..df8a88138 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinProperties.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinProperties.java @@ -28,16 +28,17 @@ import zipkin2.codec.SpanBytesEncoder; */ @ConfigurationProperties("spring.zipkin") public class ZipkinProperties { + /** - * URL of the zipkin query server instance. You can also provide - * the service id of the Zipkin server if Zipkin's registered in - * service discovery (e.g. http://zipkinserver/) + * URL of the zipkin query server instance. You can also provide the service id of the + * Zipkin server if Zipkin's registered in service discovery (e.g. + * http://zipkinserver/) */ private String baseUrl = "http://localhost:9411/"; /** - * If set to {@code false}, will treat the {@link ZipkinProperties#baseUrl} - * as a URL always + * If set to {@code false}, will treat the {@link ZipkinProperties#baseUrl} as a URL + * always */ private Boolean discoveryClientEnabled; @@ -45,13 +46,15 @@ public class ZipkinProperties { * Enables sending spans to Zipkin */ private boolean enabled = true; + /** * Timeout in seconds before pending spans will be sent in batches to Zipkin */ private int messageTimeout = 1; + /** - * Encoding type of spans sent to Zipkin. Set to {@link SpanBytesEncoder#JSON_V1} if your server - * is not recent. + * Encoding type of spans sent to Zipkin. Set to {@link SpanBytesEncoder#JSON_V1} if + * your server is not recent. */ private SpanBytesEncoder encoder = SpanBytesEncoder.JSON_V2; @@ -140,12 +143,19 @@ public class ZipkinProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } - /** When set will override the default {@code spring.application.name} value of the service id */ + /** + * When set will override the default {@code spring.application.name} value of the + * service id + */ public static class Service { - /** The name of the service, from which the Span was sent via HTTP, that should appear in Zipkin */ + /** + * The name of the service, from which the Span was sent via HTTP, that should + * appear in Zipkin + */ private String name; public String getName() { @@ -155,12 +165,13 @@ public class ZipkinProperties { public void setName(String name) { this.name = name; } + } - /** Configuration related to locating of the host name from service discovery. - * This property is NOT related to finding Zipkin via Service Disovery. - * To do so use the {@link ZipkinProperties#baseUrl} property with the - * service name set inside the URL. + /** + * Configuration related to locating of the host name from service discovery. This + * property is NOT related to finding Zipkin via Service Disovery. To do so use the + * {@link ZipkinProperties#baseUrl} property with the service name set inside the URL. */ public static class Locator { @@ -186,6 +197,9 @@ public class ZipkinProperties { public void setEnabled(boolean enabled) { this.enabled = enabled; } + } + } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinRestTemplateCustomizer.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinRestTemplateCustomizer.java index ecfcffbe0..56b4a5e02 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinRestTemplateCustomizer.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/ZipkinRestTemplateCustomizer.java @@ -19,17 +19,18 @@ package org.springframework.cloud.sleuth.zipkin2; import org.springframework.web.client.RestTemplate; /** - * Implementations customize the {@link RestTemplate} used to report spans to Zipkin. - * For example, they can add an additional header needed by their environment. + * Implementations customize the {@link RestTemplate} used to report spans to Zipkin. For + * example, they can add an additional header needed by their environment. * - *

    Implementors must gzip according to {@link ZipkinProperties.Compression}, - * for example by using the {@link DefaultZipkinRestTemplateCustomizer}. + *

    + * Implementors must gzip according to {@link ZipkinProperties.Compression}, for example + * by using the {@link DefaultZipkinRestTemplateCustomizer}. * * @author Marcin Grzejszczak - * * @since 1.1.0 */ public interface ZipkinRestTemplateCustomizer { void customize(RestTemplate restTemplate); + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/LoadBalancerClientZipkinLoadBalancer.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/LoadBalancerClientZipkinLoadBalancer.java index 8f1f6e177..ab161b269 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/LoadBalancerClientZipkinLoadBalancer.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/LoadBalancerClientZipkinLoadBalancer.java @@ -26,6 +26,7 @@ import org.springframework.cloud.sleuth.zipkin2.ZipkinProperties; class LoadBalancerClientZipkinLoadBalancer implements ZipkinLoadBalancer { private final LoadBalancerClient loadBalancerClient; + private final ZipkinProperties zipkinProperties; LoadBalancerClientZipkinLoadBalancer(LoadBalancerClient loadBalancerClient, @@ -46,4 +47,5 @@ class LoadBalancerClientZipkinLoadBalancer implements ZipkinLoadBalancer { } return URI.create(this.zipkinProperties.getBaseUrl()); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/RestTemplateSender.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/RestTemplateSender.java index d1a21ebda..0b670b25f 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/RestTemplateSender.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/RestTemplateSender.java @@ -38,41 +38,54 @@ import zipkin2.reporter.Sender; import static zipkin2.codec.SpanBytesEncoder.JSON_V2; final class RestTemplateSender extends Sender { + final RestTemplate restTemplate; + final String url; final Encoding encoding; + final MediaType mediaType; + final BytesMessageEncoder messageEncoder; - RestTemplateSender(RestTemplate restTemplate, String baseUrl, BytesEncoder encoder) { + RestTemplateSender(RestTemplate restTemplate, String baseUrl, + BytesEncoder encoder) { this.restTemplate = restTemplate; this.encoding = encoder.encoding(); if (encoder.equals(JSON_V2)) { this.mediaType = MediaType.APPLICATION_JSON; this.url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v2/spans"; - } else if (this.encoding == Encoding.PROTO3) { + } + else if (this.encoding == Encoding.PROTO3) { this.mediaType = MediaType.parseMediaType("application/x-protobuf"); this.url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v2/spans"; - } else if (this.encoding == Encoding.JSON) { + } + else if (this.encoding == Encoding.JSON) { this.mediaType = MediaType.APPLICATION_JSON; this.url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v1/spans"; - } else { - throw new UnsupportedOperationException("Unsupported encoding: " + this.encoding.name()); + } + else { + throw new UnsupportedOperationException( + "Unsupported encoding: " + this.encoding.name()); } this.messageEncoder = BytesMessageEncoder.forEncoding(this.encoding); } - @Override public Encoding encoding() { + @Override + public Encoding encoding() { return this.encoding; } - @Override public int messageMaxBytes() { - // This will drop a span larger than 5MiB. Note: values like 512KiB benchmark better. + @Override + public int messageMaxBytes() { + // This will drop a span larger than 5MiB. Note: values like 512KiB benchmark + // better. return 5 * 1024 * 1024; } - @Override public int messageSizeInBytes(List spans) { + @Override + public int messageSizeInBytes(List spans) { return encoding().listSizeInBytes(spans); } @@ -81,7 +94,8 @@ final class RestTemplateSender extends Sender { */ transient boolean closeCalled; - @Override public Call sendSpans(List encodedSpans) { + @Override + public Call sendSpans(List encodedSpans) { if (this.closeCalled) throw new IllegalStateException("close"); return new HttpPostCall(this.messageEncoder.encode(encodedSpans)); @@ -90,7 +104,8 @@ final class RestTemplateSender extends Sender { /** * Sends an empty json message to the configured endpoint. */ - @Override public CheckResult check() { + @Override + public CheckResult check() { try { post(new byte[] { '[', ']' }); return CheckResult.OK; @@ -100,7 +115,8 @@ final class RestTemplateSender extends Sender { } } - @Override public void close() { + @Override + public void close() { this.closeCalled = true; } @@ -113,18 +129,21 @@ final class RestTemplateSender extends Sender { } class HttpPostCall extends Call.Base { + private final byte[] message; HttpPostCall(byte[] message) { this.message = message; } - @Override protected Void doExecute() throws IOException { + @Override + protected Void doExecute() throws IOException { post(this.message); return null; } - @Override protected void doEnqueue(Callback callback) { + @Override + protected void doEnqueue(Callback callback) { try { post(this.message); callback.onSuccess(null); @@ -134,8 +153,11 @@ final class RestTemplateSender extends Sender { } } - @Override public Call clone() { + @Override + public Call clone() { return new HttpPostCall(this.message); } + } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinKafkaSenderConfiguration.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinKafkaSenderConfiguration.java index b625e7ef8..0bb3116c8 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinKafkaSenderConfiguration.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinKafkaSenderConfiguration.java @@ -38,10 +38,12 @@ import zipkin2.reporter.kafka11.KafkaSender; @Conditional(ZipkinSenderCondition.class) @ConditionalOnProperty(value = "spring.zipkin.sender.type", havingValue = "kafka") class ZipkinKafkaSenderConfiguration { + @Value("${spring.zipkin.kafka.topic:zipkin}") private String topic; - @Bean Sender kafkaSender(KafkaProperties config) { + @Bean + Sender kafkaSender(KafkaProperties config) { Map properties = config.buildProducerProperties(); properties.put("key.serializer", ByteArraySerializer.class.getName()); properties.put("value.serializer", ByteArraySerializer.class.getName()); @@ -50,10 +52,7 @@ class ZipkinKafkaSenderConfiguration { if (bootstrapServers instanceof List) { properties.put("bootstrap.servers", join((List) bootstrapServers)); } - return KafkaSender.newBuilder() - .topic(this.topic) - .overrides(properties) - .build(); + return KafkaSender.newBuilder().topic(this.topic).overrides(properties).build(); } static String join(List parts) { @@ -66,4 +65,5 @@ class ZipkinKafkaSenderConfiguration { } return to.toString(); } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRabbitSenderConfiguration.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRabbitSenderConfiguration.java index 16ebc1964..3ce3bb491 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRabbitSenderConfiguration.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRabbitSenderConfiguration.java @@ -32,14 +32,16 @@ import zipkin2.reporter.amqp.RabbitMQSender; @ConditionalOnMissingBean(Sender.class) @Conditional(ZipkinSenderCondition.class) class ZipkinRabbitSenderConfiguration { + @Value("${spring.zipkin.rabbitmq.queue:zipkin}") private String queue; - @Bean Sender rabbitSender(CachingConnectionFactory connectionFactory, RabbitProperties config) { + @Bean + Sender rabbitSender(CachingConnectionFactory connectionFactory, + RabbitProperties config) { return RabbitMQSender.newBuilder() .connectionFactory(connectionFactory.getRabbitConnectionFactory()) - .queue(this.queue) - .addresses(config.determineAddresses()) - .build(); + .queue(this.queue).addresses(config.determineAddresses()).build(); } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java index a8cfe6bbc..c634228bc 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java @@ -46,7 +46,9 @@ import zipkin2.reporter.Sender; @Conditional(ZipkinSenderCondition.class) @EnableConfigurationProperties(ZipkinSenderProperties.class) class ZipkinRestTemplateSenderConfiguration { - @Autowired ZipkinUrlExtractor extractor; + + @Autowired + ZipkinUrlExtractor extractor; @Bean @ConditionalOnMissingBean @@ -54,19 +56,23 @@ class ZipkinRestTemplateSenderConfiguration { ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer) { RestTemplate restTemplate = new ZipkinRestTemplateWrapper(zipkin, this.extractor); zipkinRestTemplateCustomizer.customize(restTemplate); - return new RestTemplateSender(restTemplate, zipkin.getBaseUrl(), zipkin.getEncoder()); + return new RestTemplateSender(restTemplate, zipkin.getBaseUrl(), + zipkin.getEncoder()); } @Configuration @ConditionalOnMissingClass("org.springframework.cloud.client.loadbalancer.LoadBalancerClient") static class DefaultZipkinUrlExtractorConfiguration { - @Autowired(required = false) LoadBalancerClient client; + + @Autowired(required = false) + LoadBalancerClient client; @Bean @ConditionalOnMissingBean ZipkinLoadBalancer noOpLoadBalancer(final ZipkinProperties zipkinProperties) { return new NoOpZipkinLoadBalancer(zipkinProperties); } + } @Configuration @@ -76,24 +82,32 @@ class ZipkinRestTemplateSenderConfiguration { @Configuration @ConditionalOnProperty(value = "spring.zipkin.discoveryClientEnabled", havingValue = "true", matchIfMissing = true) static class ZipkinClientLoadBalancedConfiguration { - @Autowired(required = false) LoadBalancerClient client; + + @Autowired(required = false) + LoadBalancerClient client; @Bean @ConditionalOnMissingBean - ZipkinLoadBalancer loadBalancerClientZipkinLoadBalancer(ZipkinProperties zipkinProperties) { - return new LoadBalancerClientZipkinLoadBalancer(this.client, zipkinProperties); + ZipkinLoadBalancer loadBalancerClientZipkinLoadBalancer( + ZipkinProperties zipkinProperties) { + return new LoadBalancerClientZipkinLoadBalancer(this.client, + zipkinProperties); } + } @Configuration @ConditionalOnProperty(value = "spring.zipkin.discoveryClientEnabled", havingValue = "false") static class ZipkinClientNoOpConfiguration { + @Bean @ConditionalOnMissingBean ZipkinLoadBalancer noOpLoadBalancer(final ZipkinProperties zipkinProperties) { return new NoOpZipkinLoadBalancer(zipkinProperties); } + } + } @Bean @@ -105,17 +119,20 @@ class ZipkinRestTemplateSenderConfiguration { } }; } + } /** - * Resolves at runtime where the Zipkin server is. If there's no discovery client then {@link URI} - * from the properties is taken. Otherwise service discovery is pinged for current Zipkin address. + * Resolves at runtime where the Zipkin server is. If there's no discovery client then + * {@link URI} from the properties is taken. Otherwise service discovery is pinged for + * current Zipkin address. */ class ZipkinRestTemplateWrapper extends RestTemplate { private static final Log log = LogFactory.getLog(ZipkinRestTemplateWrapper.class); private final ZipkinProperties zipkinProperties; + private final ZipkinUrlExtractor extractor; ZipkinRestTemplateWrapper(ZipkinProperties zipkinProperties, @@ -124,9 +141,10 @@ class ZipkinRestTemplateWrapper extends RestTemplate { this.extractor = extractor; } - @Override protected T doExecute(URI originalUrl, HttpMethod method, - RequestCallback requestCallback, - ResponseExtractor responseExtractor) throws RestClientException { + @Override + protected T doExecute(URI originalUrl, HttpMethod method, + RequestCallback requestCallback, ResponseExtractor responseExtractor) + throws RestClientException { URI uri = this.extractor.zipkinUrl(this.zipkinProperties); URI newUri = resolvedZipkinUri(originalUrl, uri); return super.doExecute(newUri, method, requestCallback, responseExtractor); @@ -135,27 +153,30 @@ class ZipkinRestTemplateWrapper extends RestTemplate { private URI resolvedZipkinUri(URI originalUrl, URI resolvedZipkinUri) { try { return new URI(resolvedZipkinUri.getScheme(), resolvedZipkinUri.getUserInfo(), - resolvedZipkinUri.getHost(), resolvedZipkinUri.getPort(), originalUrl.getPath(), - originalUrl.getQuery(), originalUrl.getFragment()); - } catch (URISyntaxException e) { + resolvedZipkinUri.getHost(), resolvedZipkinUri.getPort(), + originalUrl.getPath(), originalUrl.getQuery(), + originalUrl.getFragment()); + } + catch (URISyntaxException e) { if (log.isDebugEnabled()) { - log.debug("Failed to create the new URI from original [" - + originalUrl - + "] and new one [" - + resolvedZipkinUri - + "]"); + log.debug("Failed to create the new URI from original [" + originalUrl + + "] and new one [" + resolvedZipkinUri + "]"); } return originalUrl; } } + } /** - * Internal interface to provide a way to retrieve Zipkin URI. If there's no discovery client then - * this value will be taken from the properties. Otherwise host will be assumed to be a service id. + * Internal interface to provide a way to retrieve Zipkin URI. If there's no discovery + * client then this value will be taken from the properties. Otherwise host will be + * assumed to be a service id. */ interface ZipkinUrlExtractor { + URI zipkinUrl(ZipkinProperties zipkinProperties); + } class NoOpZipkinLoadBalancer implements ZipkinLoadBalancer { @@ -166,7 +187,9 @@ class NoOpZipkinLoadBalancer implements ZipkinLoadBalancer { this.zipkinProperties = zipkinProperties; } - @Override public URI instance() { + @Override + public URI instance() { return URI.create(this.zipkinProperties.getBaseUrl()); } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderCondition.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderCondition.java index 6c2f57ae1..361c8287e 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderCondition.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderCondition.java @@ -31,12 +31,14 @@ import static org.springframework.cloud.sleuth.zipkin2.sender.ZipkinSenderConfig class ZipkinSenderCondition extends SpringBootCondition { @Override - public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata md) { + public ConditionOutcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata md) { String sourceClass = ""; if (md instanceof ClassMetadata) { sourceClass = ((ClassMetadata) md).getClassName(); } - ConditionMessage.Builder message = ConditionMessage.forCondition("ZipkinSender", sourceClass); + ConditionMessage.Builder message = ConditionMessage.forCondition("ZipkinSender", + sourceClass); String property = context.getEnvironment() .getProperty("spring.zipkin.sender.type"); if (StringUtils.isEmpty(property)) { @@ -48,4 +50,5 @@ class ZipkinSenderCondition extends SpringBootCondition { } return ConditionOutcome.noMatch(message.because(property + " sender type")); } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderConfigurationImportSelector.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderConfigurationImportSelector.java index 731014cc1..ca8d6579a 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderConfigurationImportSelector.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderConfigurationImportSelector.java @@ -47,6 +47,8 @@ public class ZipkinSenderConfigurationImportSelector implements ImportSelector { return entry.getKey(); } } - throw new IllegalStateException("Unknown configuration class " + configurationClassName); + throw new IllegalStateException( + "Unknown configuration class " + configurationClassName); } + } diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderProperties.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderProperties.java index a599ed81c..d090c4476 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderProperties.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinSenderProperties.java @@ -41,6 +41,9 @@ public class ZipkinSenderProperties { } public enum SenderType { + RABBIT, KAFKA, WEB + } + } diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/DefaultEndpointLocatorConfigurationTest.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/DefaultEndpointLocatorConfigurationTest.java index 46775fb96..c121624d7 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/DefaultEndpointLocatorConfigurationTest.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/DefaultEndpointLocatorConfigurationTest.java @@ -73,7 +73,7 @@ public class DefaultEndpointLocatorConfigurationTest { public void endpointLocatorShouldSetServiceNameToServiceId() { ConfigurableApplicationContext ctxt = new SpringApplication( ConfigurationWithRegistration.class).run("--spring.jmx.enabled=false", - "--spring.zipkin.locator.discovery.enabled=true"); + "--spring.zipkin.locator.discovery.enabled=true"); assertThat(ctxt.getBean(EndpointLocator.class).local().serviceName()) .isEqualTo("from-registration"); ctxt.close(); @@ -83,8 +83,8 @@ public class DefaultEndpointLocatorConfigurationTest { public void endpointLocatorShouldAcceptServiceNameOverride() { ConfigurableApplicationContext ctxt = new SpringApplication( ConfigurationWithRegistration.class).run("--spring.jmx.enabled=false", - "--spring.zipkin.locator.discovery.enabled=true", - "--spring.zipkin.service.name=foo"); + "--spring.zipkin.locator.discovery.enabled=true", + "--spring.zipkin.service.name=foo"); assertThat(ctxt.getBean(EndpointLocator.class).local().serviceName()) .isEqualTo("foo"); ctxt.close(); @@ -93,9 +93,9 @@ public class DefaultEndpointLocatorConfigurationTest { @Test public void endpointLocatorShouldRespectExistingEndpointLocatorEvenWhenAskedToBeDiscovery() { ConfigurableApplicationContext ctxt = new SpringApplication( - ConfigurationWithRegistration.class, - ConfigurationWithCustomLocator.class).run("--spring.jmx.enabled=false", - "--spring.zipkin.locator.discovery.enabled=true"); + ConfigurationWithRegistration.class, ConfigurationWithCustomLocator.class) + .run("--spring.jmx.enabled=false", + "--spring.zipkin.locator.discovery.enabled=true"); assertThat(ctxt.getBean(EndpointLocator.class)) .isSameAs(ConfigurationWithCustomLocator.locator); ctxt.close(); @@ -104,12 +104,15 @@ public class DefaultEndpointLocatorConfigurationTest { @Configuration @EnableAutoConfiguration public static class EmptyConfiguration { + } @Configuration @EnableAutoConfiguration public static class ConfigurationWithRegistration { - @Bean public Registration getRegistration() { + + @Bean + public Registration getRegistration() { return new Registration() { @Override public String getServiceId() { @@ -142,18 +145,24 @@ public class DefaultEndpointLocatorConfigurationTest { } }; } + } @Configuration @EnableAutoConfiguration public static class ConfigurationWithCustomLocator { + static EndpointLocator locator = Mockito.mock(EndpointLocator.class); - @Bean public EndpointLocator getEndpointLocator() { + @Bean + public EndpointLocator getEndpointLocator() { return locator; } + } + public static final byte[] ADDRESS1234 = { 1, 2, 3, 4 }; + Environment environment = new MockEnvironment(); @Test @@ -170,8 +179,8 @@ public class DefaultEndpointLocatorConfigurationTest { ServerProperties properties = new ServerProperties(); properties.setPort(1234); - DefaultEndpointLocator locator = new DefaultEndpointLocator(null, - properties, environment, new ZipkinProperties(),localAddress(ADDRESS1234)); + DefaultEndpointLocator locator = new DefaultEndpointLocator(null, properties, + environment, new ZipkinProperties(), localAddress(ADDRESS1234)); assertThat(locator.local().port()).isEqualTo(1234); } @@ -179,7 +188,8 @@ public class DefaultEndpointLocatorConfigurationTest { @Test public void portDefaultsToLocalhost() throws UnknownHostException { DefaultEndpointLocator locator = new DefaultEndpointLocator(null, - new ServerProperties(), environment, new ZipkinProperties(), localAddress(ADDRESS1234)); + new ServerProperties(), environment, new ZipkinProperties(), + localAddress(ADDRESS1234)); assertThat(locator.local().ipv4()).isEqualTo("1.2.3.4"); } @@ -189,8 +199,8 @@ public class DefaultEndpointLocatorConfigurationTest { ServerProperties properties = new ServerProperties(); properties.setAddress(InetAddress.getByAddress(ADDRESS1234)); - DefaultEndpointLocator locator = new DefaultEndpointLocator(null, - properties, environment, new ZipkinProperties(), + DefaultEndpointLocator locator = new DefaultEndpointLocator(null, properties, + environment, new ZipkinProperties(), localAddress(new byte[] { 4, 4, 4, 4 })); assertThat(locator.local().ipv4()).isEqualTo("1.2.3.4"); @@ -202,8 +212,8 @@ public class DefaultEndpointLocatorConfigurationTest { ZipkinProperties zipkinProperties = new ZipkinProperties(); zipkinProperties.getService().setName("foo"); - DefaultEndpointLocator locator = new DefaultEndpointLocator(null, - properties, environment, zipkinProperties,localAddress(ADDRESS1234)); + DefaultEndpointLocator locator = new DefaultEndpointLocator(null, properties, + environment, zipkinProperties, localAddress(ADDRESS1234)); assertThat(locator.local().serviceName()).isEqualTo("foo"); } @@ -213,8 +223,8 @@ public class DefaultEndpointLocatorConfigurationTest { ServerProperties properties = new ServerProperties(); properties.setPort(-1); - DefaultEndpointLocator locator = new DefaultEndpointLocator(null, - properties, environment, new ZipkinProperties(),localAddress(ADDRESS1234)); + DefaultEndpointLocator locator = new DefaultEndpointLocator(null, properties, + environment, new ZipkinProperties(), localAddress(ADDRESS1234)); assertThat(locator.local().port()).isEqualTo(8080); } @@ -225,4 +235,5 @@ public class DefaultEndpointLocatorConfigurationTest { .thenReturn(InetAddress.getByAddress(address)); return mocked; } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfigurationTests.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfigurationTests.java index cbf19bc1d..41551e439 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfigurationTests.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfigurationTests.java @@ -49,8 +49,12 @@ import static org.assertj.core.api.BDDAssertions.then; */ public class ZipkinAutoConfigurationTests { - @Rule public ExpectedException thrown = ExpectedException.none(); - @Rule public MockWebServer server = new MockWebServer(); + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Rule + public MockWebServer server = new MockWebServer(); + MockEnvironment environment = new MockEnvironment(); AnnotationConfigApplicationContext context; @@ -66,20 +70,17 @@ public class ZipkinAutoConfigurationTests { public void defaultsToV2Endpoint() throws Exception { context = new AnnotationConfigApplicationContext(); environment().setProperty("spring.zipkin.base-url", server.url("/").toString()); - context.register( - ZipkinAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, - TraceAutoConfiguration.class, + context.register(ZipkinAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class, Config.class); context.refresh(); - Span span = - context.getBean(Tracing.class).tracer().nextSpan() - .name("foo").tag("foo", "bar") - .start(); + Span span = context.getBean(Tracing.class).tracer().nextSpan().name("foo") + .tag("foo", "bar").start(); span.finish(); - Awaitility.await().untilAsserted(() -> then(server.getRequestCount()).isGreaterThan(0)); + Awaitility.await() + .untilAsserted(() -> then(server.getRequestCount()).isGreaterThan(0)); RecordedRequest request = server.takeRequest(); then(request.getPath()).isEqualTo("/api/v2/spans"); then(request.getBody().readUtf8()).contains("localEndpoint"); @@ -95,20 +96,17 @@ public class ZipkinAutoConfigurationTests { context = new AnnotationConfigApplicationContext(); environment().setProperty("spring.zipkin.base-url", server.url("/").toString()); environment().setProperty("spring.zipkin.encoder", "JSON_V1"); - context.register( - ZipkinAutoConfiguration.class, - PropertyPlaceholderAutoConfiguration.class, - TraceAutoConfiguration.class, + context.register(ZipkinAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class, Config.class); context.refresh(); - Span span = - context.getBean(Tracing.class).tracer().nextSpan() - .name("foo").tag("foo", "bar") - .start(); + Span span = context.getBean(Tracing.class).tracer().nextSpan().name("foo") + .tag("foo", "bar").start(); span.finish(); - Awaitility.await().untilAsserted(() -> then(server.getRequestCount()).isGreaterThan(0)); + Awaitility.await() + .untilAsserted(() -> then(server.getRequestCount()).isGreaterThan(0)); RecordedRequest request = server.takeRequest(); then(request.getPath()).isEqualTo("/api/v1/spans"); then(request.getBody().readUtf8()).contains("binaryAnnotations"); @@ -118,10 +116,8 @@ public class ZipkinAutoConfigurationTests { public void overrideRabbitMQQueue() throws Exception { context = new AnnotationConfigApplicationContext(); environment().setProperty("spring.zipkin.rabbitmq.queue", "zipkin2"); - context.register( - PropertyPlaceholderAutoConfiguration.class, - RabbitAutoConfiguration.class, - ZipkinAutoConfiguration.class); + context.register(PropertyPlaceholderAutoConfiguration.class, + RabbitAutoConfiguration.class, ZipkinAutoConfiguration.class); context.refresh(); then(context.getBean(Sender.class)).isInstanceOf(RabbitMQSender.class); @@ -134,10 +130,8 @@ public class ZipkinAutoConfigurationTests { context = new AnnotationConfigApplicationContext(); environment().setProperty("spring.zipkin.kafka.topic", "zipkin2"); environment().setProperty("spring.zipkin.sender.type", "kafka"); - context.register( - PropertyPlaceholderAutoConfiguration.class, - KafkaAutoConfiguration.class, - ZipkinAutoConfiguration.class); + context.register(PropertyPlaceholderAutoConfiguration.class, + KafkaAutoConfiguration.class, ZipkinAutoConfiguration.class); context.refresh(); then(context.getBean(Sender.class)).isInstanceOf(KafkaSender.class); @@ -149,14 +143,13 @@ public class ZipkinAutoConfigurationTests { public void canOverrideBySender() throws Exception { context = new AnnotationConfigApplicationContext(); environment().setProperty("spring.zipkin.sender.type", "web"); - context.register( - PropertyPlaceholderAutoConfiguration.class, - RabbitAutoConfiguration.class, - KafkaAutoConfiguration.class, + context.register(PropertyPlaceholderAutoConfiguration.class, + RabbitAutoConfiguration.class, KafkaAutoConfiguration.class, ZipkinAutoConfiguration.class); context.refresh(); - then(context.getBean(Sender.class).getClass().getName()).contains("RestTemplateSender"); + then(context.getBean(Sender.class).getClass().getName()) + .contains("RestTemplateSender"); context.close(); } @@ -165,14 +158,13 @@ public class ZipkinAutoConfigurationTests { public void canOverrideBySenderAndIsCaseInsensitive() throws Exception { context = new AnnotationConfigApplicationContext(); environment().setProperty("spring.zipkin.sender.type", "WEB"); - context.register( - PropertyPlaceholderAutoConfiguration.class, - RabbitAutoConfiguration.class, - KafkaAutoConfiguration.class, + context.register(PropertyPlaceholderAutoConfiguration.class, + RabbitAutoConfiguration.class, KafkaAutoConfiguration.class, ZipkinAutoConfiguration.class); context.refresh(); - then(context.getBean(Sender.class).getClass().getName()).contains("RestTemplateSender"); + then(context.getBean(Sender.class).getClass().getName()) + .contains("RestTemplateSender"); context.close(); } @@ -180,10 +172,8 @@ public class ZipkinAutoConfigurationTests { @Test public void rabbitWinsWhenKafkaPresent() throws Exception { context = new AnnotationConfigApplicationContext(); - context.register( - PropertyPlaceholderAutoConfiguration.class, - RabbitAutoConfiguration.class, - KafkaAutoConfiguration.class, + context.register(PropertyPlaceholderAutoConfiguration.class, + RabbitAutoConfiguration.class, KafkaAutoConfiguration.class, ZipkinAutoConfiguration.class); context.refresh(); @@ -194,29 +184,39 @@ public class ZipkinAutoConfigurationTests { @Configuration protected static class Config { - @Bean Sampler sampler() { + + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } + } @Configuration protected static class HandlerHanldersConfig { - @Bean FinishedSpanHandler handlerOne() { + + @Bean + FinishedSpanHandler handlerOne() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name("foo"); return true; // keep this span } }; } - @Bean FinishedSpanHandler handlerTwo() { + @Bean + FinishedSpanHandler handlerTwo() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name(span.name() + " bar"); return true; // keep this span } }; } + } + } diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java index bb1425a35..378500756 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinDiscoveryClientTests.java @@ -42,14 +42,22 @@ import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringRunner.class) @SpringBootTest(classes = ZipkinDiscoveryClientTests.Config.class, properties = { - "spring.zipkin.baseUrl=http://zipkin/", - "spring.zipkin.sender.type=web" // override default priority which picks rabbit due to classpath + "spring.zipkin.baseUrl=http://zipkin/", "spring.zipkin.sender.type=web" // override + // default + // priority + // which + // picks + // rabbit + // due to + // classpath }) public class ZipkinDiscoveryClientTests { - @ClassRule public static MockWebServer ZIPKIN_RULE = new MockWebServer(); + @ClassRule + public static MockWebServer ZIPKIN_RULE = new MockWebServer(); - @Autowired Tracing tracing; + @Autowired + Tracing tracing; @Test public void shouldUseDiscoveryClientToFindZipkinUrlIfPresent() throws Exception { @@ -57,36 +65,41 @@ public class ZipkinDiscoveryClientTests { span.finish(); - Awaitility.await().untilAsserted(() -> then(ZIPKIN_RULE.getRequestCount()).isGreaterThan(0)); + Awaitility.await().untilAsserted( + () -> then(ZIPKIN_RULE.getRequestCount()).isGreaterThan(0)); } @Configuration @EnableAutoConfiguration static class Config { - @Bean Sampler sampler() { + @Bean + Sampler sampler() { return Sampler.ALWAYS_SAMPLE; } - @Bean LoadBalancerClient loadBalancerClient() { + @Bean + LoadBalancerClient loadBalancerClient() { return new LoadBalancerClient() { - @Override public T execute(String serviceId, - LoadBalancerRequest request) throws IOException { - return null; - } - - @Override public T execute(String serviceId, - ServiceInstance serviceInstance, LoadBalancerRequest request) + @Override + public T execute(String serviceId, LoadBalancerRequest request) throws IOException { return null; } - @Override public URI reconstructURI(ServiceInstance instance, - URI original) { + @Override + public T execute(String serviceId, ServiceInstance serviceInstance, + LoadBalancerRequest request) throws IOException { return null; } - @Override public ServiceInstance choose(String serviceId) { + @Override + public URI reconstructURI(ServiceInstance instance, URI original) { + return null; + } + + @Override + public ServiceInstance choose(String serviceId) { return new ServiceInstance() { @Override public String getServiceId() { @@ -121,5 +134,7 @@ public class ZipkinDiscoveryClientTests { } }; } + } + } \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinWithDisabledSleuthTests.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinWithDisabledSleuthTests.java index 0af2bd2fb..898efdf8e 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinWithDisabledSleuthTests.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinWithDisabledSleuthTests.java @@ -27,11 +27,14 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @TestPropertySource(properties = "spring.sleuth.enabled=false") public class ZipkinWithDisabledSleuthTests { - @Test public void shouldStartContext() { + @Test + public void shouldStartContext() { } @EnableAutoConfiguration static class Config { + } + } diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/sender/RestTemplateSenderTest.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/sender/RestTemplateSenderTest.java index 021ab6c5f..538abe0a4 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/sender/RestTemplateSenderTest.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/sender/RestTemplateSenderTest.java @@ -35,57 +35,54 @@ import static zipkin2.codec.SpanBytesEncoder.JSON_V2; import static zipkin2.codec.SpanBytesEncoder.PROTO3; public class RestTemplateSenderTest { - static final Span SPAN = Span.newBuilder() - .traceId("7180c278b62e8f6a216a2aea45d08fc9") - .parentId("6b221d5bc9e6496c") - .id("5b4185666d50f68b") - .name("get /backend") - .kind(Span.Kind.SERVER) - .shared(true) - .localEndpoint(Endpoint.newBuilder() - .serviceName("backend") - .ip("192.168.99.101") - .port(9000) - .build()) - .timestamp(1472470996250000L) - .duration(100000L) - .putTag("http.method", "GET") - .putTag("http.path", "/backend") - .build(); - @Rule public MockWebServer server = new MockWebServer(); + static final Span SPAN = Span.newBuilder().traceId("7180c278b62e8f6a216a2aea45d08fc9") + .parentId("6b221d5bc9e6496c").id("5b4185666d50f68b").name("get /backend") + .kind(Span.Kind.SERVER).shared(true) + .localEndpoint(Endpoint.newBuilder().serviceName("backend") + .ip("192.168.99.101").port(9000).build()) + .timestamp(1472470996250000L).duration(100000L).putTag("http.method", "GET") + .putTag("http.path", "/backend").build(); - String endpoint = server.url("/api/v2/spans").toString(); - RestTemplateSender sender = new RestTemplateSender(new RestTemplate(), endpoint, JSON_V2); + @Rule + public MockWebServer server = new MockWebServer(); - /** Tests that json is not manipulated as a side-effect of using rest template. */ - @Test public void jsonIsNormal() throws Exception { - server.enqueue(new MockResponse()); + String endpoint = server.url("/api/v2/spans").toString(); - send(SPAN).execute(); + RestTemplateSender sender = new RestTemplateSender(new RestTemplate(), endpoint, + JSON_V2); - assertThat(server.takeRequest().getBody().readUtf8()) - .isEqualTo("[" + new String(JSON_V2.encode(SPAN), "UTF-8") + "]"); - } + /** Tests that json is not manipulated as a side-effect of using rest template. */ + @Test + public void jsonIsNormal() throws Exception { + server.enqueue(new MockResponse()); - @Test public void proto3() throws Exception { - server.enqueue(new MockResponse()); - sender = new RestTemplateSender(new RestTemplate(), endpoint, PROTO3); + send(SPAN).execute(); - send(SPAN).execute(); + assertThat(server.takeRequest().getBody().readUtf8()) + .isEqualTo("[" + new String(JSON_V2.encode(SPAN), "UTF-8") + "]"); + } - RecordedRequest request = server.takeRequest(); - assertThat(request.getHeader("Content-Type")) - .isEqualTo("application/x-protobuf"); + @Test + public void proto3() throws Exception { + server.enqueue(new MockResponse()); + sender = new RestTemplateSender(new RestTemplate(), endpoint, PROTO3); - // proto3 encoding of ListOfSpan is simply a repeated span entry - assertThat(request.getBody().readByteArray()) - .containsExactly(SpanBytesEncoder.PROTO3.encode(SPAN)); - } + send(SPAN).execute(); + + RecordedRequest request = server.takeRequest(); + assertThat(request.getHeader("Content-Type")).isEqualTo("application/x-protobuf"); + + // proto3 encoding of ListOfSpan is simply a repeated span entry + assertThat(request.getBody().readByteArray()) + .containsExactly(SpanBytesEncoder.PROTO3.encode(SPAN)); + } + + Call send(Span... spans) { + SpanBytesEncoder bytesEncoder = sender.encoding() == Encoding.JSON + ? SpanBytesEncoder.JSON_V2 : SpanBytesEncoder.PROTO3; + return sender + .sendSpans(Stream.of(spans).map(bytesEncoder::encode).collect(toList())); + } - Call send(Span... spans) { - SpanBytesEncoder bytesEncoder = sender.encoding() == Encoding.JSON - ? SpanBytesEncoder.JSON_V2 : SpanBytesEncoder.PROTO3; - return sender.sendSpans(Stream.of(spans).map(bytesEncoder::encode).collect(toList())); - } }