diff --git a/README.adoc b/README.adoc index f41392b83..162362d60 100644 --- a/README.adoc +++ b/README.adoc @@ -1,7 +1,6 @@ // Do not edit this file (e.g. go instead to src/main/asciidoc) -image::https://api.travis-ci.org/spring-cloud/spring-cloud-sleuth.svg?branch=master[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-sleuth] -image::https://badges.gitter.im/spring-cloud/spring-cloud-sleuth.svg[Gitter, link="https://gitter.im/spring-cloud/spring-cloud-sleuth?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] +image::https://api.travis-ci.org/spring-cloud/spring-cloud-sleuth.svg?branch=master[Build Status, link=https://travis-ci.org/spring-cloud/spring-cloud-sleuth] image::https://badges.gitter.im/spring-cloud/spring-cloud-sleuth.svg[Gitter, link="https://gitter.im/spring-cloud/spring-cloud-sleuth?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] == Spring Cloud Sleuth Spring Cloud Sleuth implements a distributed tracing solution for http://cloud.spring.io[Spring Cloud]. diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java index 5552aea70..309aad05c 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java @@ -61,7 +61,7 @@ public class Span { private final long begin; private long end = 0; - private final String name; + private final SpanName name; private final long traceId; @Singular private List parents = new ArrayList<>(); @@ -93,18 +93,18 @@ public class Span { this.savedSpan = savedSpan; } - public Span(long begin, long end, String name, long traceId, List parents, + public Span(long begin, long end, SpanName name, long traceId, List parents, long spanId, boolean remote, boolean exportable, String processId) { this(begin, end, name, traceId, parents, spanId, remote, exportable, processId, null); } - public Span(long begin, long end, String name, long traceId, List parents, + public Span(long begin, long end, SpanName name, long traceId, List parents, long spanId, boolean remote, boolean exportable, String processId, Span savedSpan) { this.begin = begin <= 0 ? System.currentTimeMillis() : begin; this.end = end; - this.name = name; + this.name = name != null ? name : SpanName.NO_NAME; this.traceId = traceId; this.parents = parents; this.spanId = spanId; @@ -117,7 +117,7 @@ public class Span { // for serialization private Span() { this.begin = 0; - this.name = null; + this.name = SpanName.NO_NAME; this.traceId = 0; this.spanId = 0; this.processId = null; @@ -210,7 +210,7 @@ public class Span { * A human-readable name assigned to this span instance. *

*/ - public String getName() { + public SpanName getName() { return this.name; } 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 new file mode 100644 index 000000000..37696da70 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/SpanName.java @@ -0,0 +1,111 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.sleuth; + +import java.lang.invoke.MethodHandles; +import java.util.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +/** + * Class representing a name of the span. + * It consists of + *

  • + *
      component - means of communication e.g. http, message
    + *
      address - what the span is addressing e.g. /some/http/address, someQueueName
    + *
      fragment - additional label e.g. async
    + *
  • + * + * The template of the span name is + * + *
    component:address#fragment
    + * + * @author Marcin Grzejszczak + */ +public class SpanName { + + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + public static final SpanName NO_NAME = new SpanName("", ""); + + public final String component; + public final String address; + public final String fragment; + + // serialization + SpanName() { + this("", "", ""); + } + + public SpanName(String component, String address) { + this(component, address, ""); + } + + public SpanName(String component, String address, String fragment) { + this.component = component; + this.address = address; + this.fragment = fragment; + } + + public static SpanName fromString(String name) { + String[] splitString = name.split(":"); + if (splitString.length < 2) { + log.debug("Can't parse [{}]. Returning 'unknown' component and passing name to address", name); + return new SpanName("unknown", name); + } + String protocol = splitString[0]; + String address = name.substring(name.indexOf(":") + 1); + String fragment = ""; + if (address.contains("#")) { + String[] splitSecondArg = address.split("#"); + fragment = address.substring(address.indexOf("#") + 1); + address = splitSecondArg[0]; + } + return new SpanName(protocol, address, fragment); + } + + @Override + public String toString() { + if (this.equals(NO_NAME)) { + return ""; + } + String baseName = this.component + ":" + this.address; + if (StringUtils.hasText(this.fragment)) { + return baseName + "#" + this.fragment; + } + return baseName; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + SpanName spanName = (SpanName) o; + return Objects.equals(this.component, spanName.component) && + Objects.equals(this.address, spanName.address) && + Objects.equals(this.fragment, spanName.fragment); + } + + @Override + public int hashCode() { + return Objects.hash(this.component, this.address, this.fragment); + } +} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Tracer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Tracer.java index b312fc6e6..be3cad4b1 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Tracer.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Tracer.java @@ -55,7 +55,7 @@ public interface Tracer extends SpanAccessor { * * @param name The name field for the new span to create. */ - Span startTrace(String name); + Span startTrace(SpanName name); /** * Creates a new Span with a specific parent. The parent might be in another @@ -67,7 +67,7 @@ public interface Tracer extends SpanAccessor { * * @param name The name field for the new span to create. */ - Span joinTrace(String name, Span parent); + Span joinTrace(SpanName name, Span parent); /** * Start a new span if the sampler allows it or if we are already tracing in this @@ -75,7 +75,7 @@ public interface Tracer extends SpanAccessor { * @param name the name of the span * @param sampler a sampler to decide whether to create the span or not */ - Span startTrace(String name, Sampler sampler); + Span startTrace(SpanName name, Sampler sampler); /** * Pick up an existing span from another thread. 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 b81b510c1..5eb1278e6 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 @@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.sleuth.Tracer; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.scheduling.annotation.AsyncConfigurer; @@ -47,4 +48,9 @@ public class AsyncDefaultAutoConfiguration extends AsyncConfigurerSupport { return new LazyTraceExecutor(this.beanFactory, new SimpleAsyncTaskExecutor()); } + @Bean + public TraceAsyncAspect traceAsyncAspect(Tracer tracer) { + return new TraceAsyncAspect(tracer); + } + } \ No newline at end of file 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 new file mode 100644 index 000000000..c72d26796 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceAsyncAspect.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013-2016 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.async; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; +import org.springframework.cloud.sleuth.Tracer; + +/** + * Aspect that creates a new Span for running threads executing methods annotated with + * {@link org.springframework.scheduling.annotation.Async} annotation. + * + * @author Marcin Grzejszczak + * + * @see Tracer + */ +@Aspect +public class TraceAsyncAspect { + + private static final String ASYNC_COMPONENT = "async"; + + private final Tracer tracer; + + public TraceAsyncAspect(Tracer tracer) { + this.tracer = tracer; + } + + @Around("execution (@org.springframework.scheduling.annotation.Async * *.*(..))") + public Object traceBackgroundThread(final ProceedingJoinPoint pjp) throws Throwable { + SpanName spanName = new SpanName(ASYNC_COMPONENT, + pjp.getTarget().getClass().getSimpleName(), + "method=" + pjp.getSignature().getName()); + Span span = this.tracer.startTrace(spanName); + try { + return pjp.proceed(); + } + finally { + this.tracer.close(span); + } + } + +} 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 6ec4e250b..e2022bd2c 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 @@ -18,11 +18,11 @@ package org.springframework.cloud.sleuth.instrument.async; import java.util.concurrent.Callable; -import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.Tracer; - import lombok.EqualsAndHashCode; import lombok.Value; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; +import org.springframework.cloud.sleuth.Tracer; /** * @author Spencer Gibb @@ -35,7 +35,7 @@ public class TraceCallable extends TraceDelegate> implements Call super(tracer, delegate); } - public TraceCallable(Tracer tracer, Callable delegate, String name) { + public TraceCallable(Tracer tracer, Callable delegate, SpanName name) { super(tracer, delegate, name); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceDelegate.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceDelegate.java index 07c40c03e..c8cfee6b2 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceDelegate.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceDelegate.java @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.instrument.async; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import lombok.Getter; @@ -27,16 +28,18 @@ import lombok.Getter; @Getter public abstract class TraceDelegate { + private static final String ASYNC_COMPONENT = "async"; + private final Tracer tracer; private final T delegate; - private final String name; + private final SpanName name; private final Span parent; public TraceDelegate(Tracer tracer, T delegate) { this(tracer, delegate, null); } - public TraceDelegate(Tracer tracer, T delegate, String name) { + public TraceDelegate(Tracer tracer, T delegate, SpanName name) { this.tracer = tracer; this.delegate = delegate; this.name = name; @@ -51,8 +54,10 @@ public abstract class TraceDelegate { return this.tracer.joinTrace(getSpanName(), this.parent); } - protected String getSpanName() { - return this.name == null ? Thread.currentThread().getName() : this.name; + protected SpanName getSpanName() { + return this.name == null ? + new SpanName(ASYNC_COMPONENT, Thread.currentThread().getName()) + : this.name; } } 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 80ae3b1dc..8ad48dc6f 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 @@ -16,11 +16,11 @@ package org.springframework.cloud.sleuth.instrument.async; -import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.Tracer; - import lombok.EqualsAndHashCode; import lombok.Value; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; +import org.springframework.cloud.sleuth.Tracer; /** * @author Spencer Gibb @@ -33,7 +33,7 @@ public class TraceRunnable extends TraceDelegate implements Runnable { super(tracer, delegate); } - public TraceRunnable(Tracer tracer, Runnable delegate, String name) { + public TraceRunnable(Tracer tracer, Runnable delegate, SpanName name) { super(tracer, delegate, name); } 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 d502747ed..67144bee7 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 @@ -24,6 +24,7 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; /** * A decorator class for {@link ExecutorService} to support tracing in Executors @@ -33,15 +34,21 @@ import org.springframework.cloud.sleuth.Tracer; public class TraceableExecutorService implements ExecutorService { final ExecutorService delegate; final Tracer tracer; + private final SpanName spanName; public TraceableExecutorService(final ExecutorService delegate, final Tracer tracer) { + this(delegate, tracer, null); + } + + public TraceableExecutorService(final ExecutorService delegate, final Tracer tracer, SpanName spanName) { this.delegate = delegate; this.tracer = tracer; + this.spanName = spanName; } @Override public void execute(Runnable command) { - final Runnable r = new TraceRunnable(this.tracer, command); + final Runnable r = new TraceRunnable(this.tracer, command, this.spanName); this.delegate.execute(r); } @@ -72,19 +79,19 @@ public class TraceableExecutorService implements ExecutorService { @Override public Future submit(Callable task) { - Callable c = new TraceCallable<>(this.tracer, task); + Callable c = new TraceCallable<>(this.tracer, task, this.spanName); return this.delegate.submit(c); } @Override public Future submit(Runnable task, T result) { - Runnable r = new TraceRunnable(this.tracer, task); + Runnable r = new TraceRunnable(this.tracer, task, this.spanName); return this.delegate.submit(r, result); } @Override public Future submit(Runnable task) { - Runnable r = new TraceRunnable(this.tracer, task); + Runnable r = new TraceRunnable(this.tracer, task, this.spanName); return this.delegate.submit(r); } 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 91acd1732..b73aa5f8b 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 @@ -1,20 +1,20 @@ package org.springframework.cloud.sleuth.instrument.hystrix; -import java.util.concurrent.Callable; - import javax.annotation.PreDestroy; - -import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.Tracer; +import java.util.concurrent.Callable; import com.netflix.hystrix.strategy.HystrixPlugins; import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; - import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; +import org.springframework.cloud.sleuth.Tracer; @Slf4j public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy { + private static final String HYSTRIX_COMPONENT = "hystrix"; + private final Tracer tracer; public SleuthHystrixConcurrencyStrategy(Tracer tracer) { @@ -62,7 +62,8 @@ public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy span = this.tracer.continueSpan(span); } else { - span = this.tracer.startTrace(Thread.currentThread().getName()); + span = this.tracer.startTrace(new SpanName(HYSTRIX_COMPONENT, + Thread.currentThread().getName())); created = true; } try { 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 d5339f18a..68a1ae004 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 @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.instrument.hystrix; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import com.netflix.hystrix.HystrixCommand; @@ -33,6 +34,8 @@ import com.netflix.hystrix.HystrixCommand; */ public abstract class TraceCommand extends HystrixCommand { + private static final String HYSTRIX_COMPONENT = "hystrix"; + private final Tracer tracer; private final Span parentSpan; @@ -44,7 +47,8 @@ public abstract class TraceCommand extends HystrixCommand { @Override protected R run() throws Exception { - Span span = this.tracer.joinTrace(getCommandKey().name(), this.parentSpan); + SpanName spanName = new SpanName(HYSTRIX_COMPONENT, getCommandKey().name()); + Span span = this.tracer.joinTrace(spanName, this.parentSpan); try { return doRun(); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/AbstractTraceChannelInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/AbstractTraceChannelInterceptor.java index cb825cadb..1a3df6ad9 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/AbstractTraceChannelInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/AbstractTraceChannelInterceptor.java @@ -3,6 +3,7 @@ package org.springframework.cloud.sleuth.instrument.messaging; import java.util.Random; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.TraceKeys; import org.springframework.integration.channel.AbstractMessageChannel; @@ -20,7 +21,7 @@ import org.springframework.util.ClassUtils; */ abstract class AbstractTraceChannelInterceptor extends ChannelInterceptorAdapter implements ExecutorChannelInterceptor { - protected static final String MESSAGE_NAME_PREFIX = "message/"; + protected static final String MESSAGE_COMPONENT = "message"; private final Tracer tracer; @@ -64,7 +65,7 @@ abstract class AbstractTraceChannelInterceptor extends ChannelInterceptorAdapter String processId = getHeader(message, Span.PROCESS_ID_NAME); String spanName = getHeader(message, Span.SPAN_NAME_NAME); if (spanName != null) { - span.name(spanName); + span.name(SpanName.fromString(spanName)); } if (processId != null) { span.processId(processId); @@ -106,8 +107,8 @@ abstract class AbstractTraceChannelInterceptor extends ChannelInterceptorAdapter return name; } - String getMessageChannelName(MessageChannel channel) { - return MESSAGE_NAME_PREFIX + getChannelName(channel); + SpanName getMessageChannelName(MessageChannel channel) { + return new SpanName(MESSAGE_COMPONENT, getChannelName(channel)); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SpanMessageHeaders.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SpanMessageHeaders.java index 5924a4f5b..3f240bd40 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SpanMessageHeaders.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SpanMessageHeaders.java @@ -73,7 +73,7 @@ public class SpanMessageHeaders { if (parentId != null) { addHeader(headers, Span.PARENT_ID_NAME, Span.toHex(parentId)); } - addHeader(headers, Span.SPAN_NAME_NAME, span.getName()); + addHeader(headers, Span.SPAN_NAME_NAME, span.getName().toString()); addHeader(headers, Span.PROCESS_ID_NAME, span.getProcessId()); } else { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceChannelInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceChannelInterceptor.java index 146e04d7c..8096556ef 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceChannelInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceChannelInterceptor.java @@ -19,6 +19,7 @@ package org.springframework.cloud.sleuth.instrument.messaging; import java.util.Random; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.TraceKeys; import org.springframework.cloud.sleuth.sampler.NeverSampler; @@ -45,12 +46,12 @@ public class TraceChannelInterceptor extends AbstractTraceChannelInterceptor { public Message preSend(Message message, MessageChannel channel) { Span parentSpan = getTracer().isTracing() ? getTracer().getCurrentSpan() : buildSpan(message); - String name = getMessageChannelName(channel); + SpanName name = getMessageChannelName(channel); Span span = startSpan(parentSpan, name, message); return SpanMessageHeaders.addSpanHeaders(getTraceKeys(), message, span); } - private Span startSpan(Span span, String name, Message message) { + private Span startSpan(Span span, SpanName name, Message message) { if (span != null) { return getTracer().joinTrace(name, span); } 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 e87a2b280..d21124f44 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 @@ -20,6 +20,7 @@ import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; /** @@ -37,6 +38,8 @@ import org.springframework.cloud.sleuth.Tracer; @Aspect public class TraceSchedulingAspect { + private static final String SCHEDULED_COMPONENT = "scheduled"; + private final Tracer tracer; public TraceSchedulingAspect(Tracer tracer) { @@ -45,7 +48,10 @@ public class TraceSchedulingAspect { @Around("execution (@org.springframework.scheduling.annotation.Scheduled * *.*(..))") public Object traceBackgroundThread(final ProceedingJoinPoint pjp) throws Throwable { - Span span = this.tracer.startTrace(pjp.toShortString()); + SpanName spanName = new SpanName(SCHEDULED_COMPONENT, + pjp.getTarget().getClass().getSimpleName(), + "method=" + pjp.getSignature().getName()); + Span span = this.tracer.startTrace(spanName); try { return pjp.proceed(); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java index d678cd28d..005953f65 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java @@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Span.SpanBuilder; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.event.ServerReceivedEvent; import org.springframework.cloud.sleuth.event.ServerSentEvent; @@ -57,7 +58,7 @@ import org.springframework.web.util.UrlPathHelper; * * @see Tracer * @see TraceKeys - * @see TraceWebAutoConfiguration#traceWebFilter(TraceFilter) + * @see TraceWebAutoConfiguration#traceFilter(TraceFilter) * * @author Jakub Nabrdalik, 4financeIT * @author Tomasz Nurkiewicz, 4financeIT @@ -117,7 +118,9 @@ public class TraceFilter extends OncePerRequestFilter addToResponseIfNotPresent(response, Span.NOT_SAMPLED_NAME, ""); } - String name = "http" + uri; + String protocol = "http"; + String address = uri; + SpanName name = new SpanName(protocol, address); if (spanFromRequest == null) { if (hasHeader(request, response, Span.TRACE_ID_NAME)) { long traceId = Span @@ -133,10 +136,10 @@ public class TraceFilter extends OncePerRequestFilter String processId = getHeader(request, response, Span.PROCESS_ID_NAME); String parentName = getHeader(request, response, Span.SPAN_NAME_NAME); if (StringUtils.hasText(parentName)) { - span.name(parentName); + span.name(SpanName.fromString(parentName)); } else { - span.name("parent/" + name); + span.name(new SpanName(protocol, "/parent" + uri)); } if (StringUtils.hasText(processId)) { span.processId(processId); @@ -272,7 +275,6 @@ public class TraceFilter extends OncePerRequestFilter private String getFullUrl(HttpServletRequest request) { StringBuffer requestURI = request.getRequestURL(); String queryString = request.getQueryString(); - if (queryString == null) { return requestURI.toString(); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java index 9f807c784..af6520d93 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceHandlerInterceptor.java @@ -16,13 +16,15 @@ package org.springframework.cloud.sleuth.instrument.web; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.springframework.web.util.UrlPathHelper; /** * @author Spencer Gibb @@ -33,6 +35,8 @@ public class TraceHandlerInterceptor implements HandlerInterceptor { private final Tracer tracer; + private final UrlPathHelper urlPathHelper = new UrlPathHelper(); + public TraceHandlerInterceptor(Tracer tracer) { this.tracer = tracer; } @@ -42,7 +46,9 @@ public class TraceHandlerInterceptor implements HandlerInterceptor { Object handler) throws Exception { // TODO: get trace data from request? // TODO: what is the description? - Span span = this.tracer.startTrace("traceHandlerInterceptor"); + String uri = this.urlPathHelper.getPathWithinApplication(request); + SpanName spanName = new SpanName("http", uri, "interceptor=traceHandlerInterceptor"); + Span span = this.tracer.startTrace(spanName); request.setAttribute(ATTR_NAME, span); return true; } 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 83e171020..cfc088b88 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 @@ -16,18 +16,20 @@ package org.springframework.cloud.sleuth.instrument.web; -import lombok.extern.apachecommons.CommonsLog; +import java.lang.reflect.Field; +import java.util.concurrent.Callable; + import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.cloud.sleuth.SpanAccessor; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.async.TraceCallable; import org.springframework.web.context.request.async.WebAsyncTask; -import java.lang.reflect.Field; -import java.util.concurrent.Callable; +import lombok.extern.apachecommons.CommonsLog; /** * Aspect that adds correlation id to @@ -61,6 +63,8 @@ import java.util.concurrent.Callable; @CommonsLog public class TraceWebAspect { + private static final String ASYNC_COMPONENT = "async"; + private final Tracer tracer; private final SpanAccessor accessor; @@ -100,13 +104,19 @@ public class TraceWebAspect { if (this.accessor.isTracing()) { log.debug("Wrapping callable with span [" + this.accessor.getCurrentSpan() + "]"); - return new TraceCallable<>(this.tracer, callable); + return new TraceCallable<>(this.tracer, callable, spanName(pjp)); } else { return callable; } } + private SpanName spanName(ProceedingJoinPoint pjp) { + return new SpanName(ASYNC_COMPONENT, + pjp.getTarget().getClass().getSimpleName(), + "method=" + pjp.getSignature().getName()); + } + @Around("anyControllerOrRestControllerWithPublicWebAsyncTaskMethod()") public Object wrapWebAsyncTaskWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable { final WebAsyncTask webAsyncTask = (WebAsyncTask) pjp.proceed(); @@ -116,7 +126,8 @@ public class TraceWebAspect { + this.accessor.getCurrentSpan() + "]"); Field callableField = WebAsyncTask.class.getDeclaredField("callable"); callableField.setAccessible(true); - callableField.set(webAsyncTask, new TraceCallable<>(this.tracer, webAsyncTask.getCallable())); + callableField.set(webAsyncTask, new TraceCallable<>(this.tracer, + webAsyncTask.getCallable(), spanName(pjp))); } catch (NoSuchFieldException ex) { log.warn("Cannot wrap webAsyncTask's callable with TraceCallable", ex); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceFeignClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceFeignClientAutoConfiguration.java index de14de94b..56e81e872 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceFeignClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceFeignClientAutoConfiguration.java @@ -126,7 +126,7 @@ public class TraceFeignClientAutoConfiguration { return; } template.header(Span.TRACE_ID_NAME, Span.toHex(span.getTraceId())); - setHeader(template, Span.SPAN_NAME_NAME, span.getName()); + setHeader(template, Span.SPAN_NAME_NAME, span.getName().toString()); setHeader(template, Span.SPAN_ID_NAME, Span.toHex(span.getSpanId())); if (!span.isExportable()) { setHeader(template, Span.NOT_SAMPLED_NAME, "true"); @@ -152,18 +152,12 @@ public class TraceFeignClientAutoConfiguration { } public void setHeader(RequestTemplate request, String name, String value) { - if (value != null && !request.headers().containsKey(name) + if (StringUtils.hasText(value) && !request.headers().containsKey(name) && this.accessor.isTracing()) { request.header(name, value); } } - public void setHeader(RequestTemplate request, String name, Long value) { - if (value != null) { - setHeader(request, name, Span.toHex(value)); - } - } - private Map> headersWithTraceId( Map> headers) { Map> newHeaders = new HashMap<>(); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java index 0f2b4c648..051e837ef 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java @@ -28,6 +28,7 @@ import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.StringUtils; /** * Interceptor that verifies whether the trance and span id has been set on the request @@ -68,7 +69,7 @@ public class TraceRestTemplateInterceptor if (!span.isExportable()) { setHeader(request, Span.NOT_SAMPLED_NAME, "true"); } - setHeader(request, Span.SPAN_NAME_NAME, span.getName()); + setHeader(request, Span.SPAN_NAME_NAME, span.getName().toString()); setHeader(request, Span.PARENT_ID_NAME, getParentId(span)); setHeader(request, Span.PROCESS_ID_NAME, span.getProcessId()); publish(new ClientSentEvent(this, span)); @@ -93,7 +94,7 @@ public class TraceRestTemplateInterceptor } public void setHeader(HttpRequest request, String name, String value) { - if (value!=null && !request.getHeaders().containsKey(name) && this.accessor.isTracing()) { + if (StringUtils.hasText(value) && !request.getHeaders().containsKey(name) && this.accessor.isTracing()) { request.getHeaders().add(name, value); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilter.java index f70e2d0e6..167d2f77a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilter.java @@ -28,6 +28,7 @@ import org.springframework.util.ReflectionUtils; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; +import org.springframework.util.StringUtils; /** * @author Dave Syer @@ -68,7 +69,7 @@ public class TracePreZuulFilter extends ZuulFilter try { setHeader(response, Span.SPAN_ID_NAME, span.getSpanId()); setHeader(response, Span.TRACE_ID_NAME, span.getTraceId()); - setHeader(response, Span.SPAN_NAME_NAME, span.getName()); + setHeader(response, Span.SPAN_NAME_NAME, span.getName().toString()); if (!span.isExportable()) { setHeader(response, Span.NOT_SAMPLED_NAME, "true"); } @@ -92,7 +93,7 @@ public class TracePreZuulFilter extends ZuulFilter } public void setHeader(Map request, String name, String value) { - if (value != null && !request.containsKey(name) && this.accessor.isTracing()) { + if (StringUtils.hasText(value) && !request.containsKey(name) && this.accessor.isTracing()) { request.put(name, value); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactory.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactory.java index 29537849b..f9269dbec 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactory.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactory.java @@ -97,7 +97,7 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand } setHeader(requestBuilder, Span.TRACE_ID_NAME, Span.toHex(span.getTraceId())); setHeader(requestBuilder, Span.SPAN_ID_NAME, Span.toHex(span.getSpanId())); - setHeader(requestBuilder, Span.SPAN_NAME_NAME, span.getName()); + setHeader(requestBuilder, Span.SPAN_NAME_NAME, span.getName().toString()); setHeader(requestBuilder, Span.PARENT_ID_NAME, Span.toHex(getParentId(span))); setHeader(requestBuilder, Span.PROCESS_ID_NAME, diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTracer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTracer.java index 399e9303f..9aa7e9c3c 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTracer.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTracer.java @@ -21,6 +21,7 @@ import java.util.concurrent.Callable; import org.springframework.cloud.sleuth.Sampler; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.event.SpanAcquiredEvent; import org.springframework.cloud.sleuth.event.SpanContinuedEvent; @@ -49,7 +50,7 @@ public class DefaultTracer implements Tracer { } @Override - public Span joinTrace(String name, Span parent) { + public Span joinTrace(SpanName name, Span parent) { if (parent == null) { return startTrace(name); } @@ -57,12 +58,12 @@ public class DefaultTracer implements Tracer { } @Override - public Span startTrace(String name) { + public Span startTrace(SpanName name) { return this.startTrace(name, this.defaultSampler); } @Override - public Span startTrace(String name, Sampler sampler) { + public Span startTrace(SpanName name, Sampler sampler) { Span span; if (isTracing()) { span = createChild(getCurrentSpan(), name); @@ -128,7 +129,7 @@ public class DefaultTracer implements Tracer { return savedSpan; } - protected Span createChild(Span parent, String name) { + protected Span createChild(Span parent, SpanName name) { long id = createId(); if (parent == null) { Span span = Span.builder().begin(System.currentTimeMillis()).name(name) diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanNameTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanNameTest.java new file mode 100644 index 000000000..4fc1215c7 --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanNameTest.java @@ -0,0 +1,51 @@ +package org.springframework.cloud.sleuth; + +import org.junit.Test; + +import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then; + +/** + * @author Marcin Grzejszczak + */ +public class SpanNameTest { + + @Test + public void should_return_span_name_wihout_fragment_when_no_fragment_is_passed() { + then(new SpanName("component", "address").toString()) + .isEqualTo("component:address"); + } + + @Test + public void should_return_span_name_together_with_fragment_when_fragment_was_passed() { + then(new SpanName("component", "address", "fragment").toString()) + .isEqualTo("component:address#fragment"); + } + + @Test + public void should_return_empty_string_if_there_is_no_span_name() { + then(SpanName.NO_NAME.toString()).isEmpty(); + } + + @Test + public void should_build_span_from_valid_string_name() { + then(SpanName.fromString("http:/a/b/c#async")) + .hasComponentEqualTo("http") + .hasAddressEqualTo("/a/b/c") + .hasFragmentEqualTo("async"); + } + + @Test + public void should_build_span_from_a_string_with_missing_protocol() { + then(SpanName.fromString("/a/b/c").toString()) + .isEqualTo("unknown:/a/b/c"); + } + + @Test + public void should_build_span_from_a_string_name_with_many_separators() { + then(SpanName.fromString("http:/a/b:/c#async:asd=123#4444")) + .hasComponentEqualTo("http") + .hasAddressEqualTo("/a/b:/c") + .hasFragmentEqualTo("async:asd=123#4444"); + } + +} \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java index 4326257df..d510155ca 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java @@ -1,9 +1,9 @@ package org.springframework.cloud.sleuth; -import org.junit.Test; - import java.util.Collections; +import org.junit.Test; + import static org.assertj.core.api.BDDAssertions.then; /** @@ -37,14 +37,14 @@ public class SpanTest { } @Test(expected = UnsupportedOperationException.class) public void getAnnotationsReadOnly() { - Span span = new Span(1, 2, "name", 1L, Collections.emptyList(), 2L, true, + Span span = new Span(1, 2, new SpanName("http", "name"), 1L, Collections.emptyList(), 2L, true, true, "process"); span.tags().put("a", "b"); } @Test(expected = UnsupportedOperationException.class) public void getTimelineAnnotationsReadOnly() { - Span span = new Span(1, 2, "name", 1L, Collections.emptyList(), 2L, true, + Span span = new Span(1, 2, new SpanName("http", "name"), 1L, Collections.emptyList(), 2L, true, true, "process"); span.logs().add(new Log(1, "1")); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SleuthAssertions.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SleuthAssertions.java index bc1369f36..79b4aabc2 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SleuthAssertions.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SleuthAssertions.java @@ -2,6 +2,7 @@ package org.springframework.cloud.sleuth.assertions; import org.assertj.core.api.BDDAssertions; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; public class SleuthAssertions extends BDDAssertions { @@ -13,4 +14,12 @@ public class SleuthAssertions extends BDDAssertions { return new SpanAssert(actual); } + public static SpanNameAssert then(SpanName actual) { + return assertThat(actual); + } + + public static SpanNameAssert assertThat(SpanName actual) { + return new SpanNameAssert(actual); + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SpanAssert.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SpanAssert.java index d2e997c8d..1d274aade 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SpanAssert.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SpanAssert.java @@ -6,6 +6,7 @@ import org.assertj.core.api.AbstractAssert; import org.springframework.cloud.sleuth.Span; import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.sleuth.SpanName; @Slf4j public class SpanAssert extends AbstractAssert { @@ -28,7 +29,7 @@ public class SpanAssert extends AbstractAssert { return this; } - public SpanAssert hasNameNotEqualTo(String name) { + public SpanAssert hasNameNotEqualTo(SpanName name) { isNotNull(); if (Objects.equals(this.actual.getName(), name)) { String message = String.format("Expected span's name not to be <%s> but was <%s>", name, this.actual.getName()); @@ -38,7 +39,7 @@ public class SpanAssert extends AbstractAssert { return this; } - public SpanAssert hasNameEqualTo(String name) { + public SpanAssert hasNameEqualTo(SpanName name) { isNotNull(); if (!Objects.equals(this.actual.getName(), name)) { String message = String.format("Expected span's name to be <%s> but it was <%s>", name, this.actual.getName()); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SpanNameAssert.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SpanNameAssert.java new file mode 100644 index 000000000..7fadfdec3 --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SpanNameAssert.java @@ -0,0 +1,66 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.sleuth.assertions; + +import java.util.Objects; + +import org.assertj.core.api.AbstractAssert; +import org.springframework.cloud.sleuth.SpanName; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class SpanNameAssert extends AbstractAssert { + + public SpanNameAssert(SpanName actual) { + super(actual, SpanNameAssert.class); + } + + public static SpanNameAssert then(SpanName actual) { + return new SpanNameAssert(actual); + } + + public SpanNameAssert hasComponentEqualTo(String protocol) { + isNotNull(); + if (!Objects.equals(this.actual.component, protocol)) { + String message = String.format("Expected span name's component to be <%s> but was <%s>", protocol, this.actual.component); + log.error(message); + failWithMessage(message); + } + return this; + } + + public SpanNameAssert hasAddressEqualTo(String address) { + isNotNull(); + if (!Objects.equals(this.actual.address, address)) { + String message = String.format("Expected span name's address to be <%s> but was <%s>", address, this.actual.address); + log.error(message); + failWithMessage(message); + } + return this; + } + + public SpanNameAssert hasFragmentEqualTo(String fragment) { + isNotNull(); + if (!Objects.equals(this.actual.fragment, fragment)) { + String message = String.format("Expected span name's fragment to be <%s> but was <%s>", fragment, this.actual.fragment); + log.error(message); + failWithMessage(message); + } + return this; + } +} \ 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 53012a6fe..23b798b53 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 @@ -1,11 +1,17 @@ package org.springframework.cloud.sleuth.instrument.async; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.async.TraceCallable; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; @@ -13,11 +19,6 @@ import org.springframework.cloud.sleuth.trace.DefaultTracer; import org.springframework.cloud.sleuth.trace.TestSpanContextHolder; import org.springframework.context.ApplicationEventPublisher; -import java.util.Random; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - import static org.assertj.core.api.BDDAssertions.then; @RunWith(MockitoJUnitRunner.class) @@ -72,7 +73,7 @@ public class TraceCallableTests { } private Span givenSpanIsAlreadyActive() { - return this.tracer.startTrace("parent"); + return this.tracer.startTrace(new SpanName("http", "parent")); } private Callable thatRetrievesTraceFromThreadLocal() { 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 9550cab6e..62a0c2ff5 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 @@ -1,20 +1,5 @@ package org.springframework.cloud.sleuth.instrument.async; -import lombok.SneakyThrows; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.Tracer; -import org.springframework.cloud.sleuth.instrument.async.TraceableExecutorService; -import org.springframework.cloud.sleuth.sampler.AlwaysSampler; -import org.springframework.cloud.sleuth.trace.DefaultTracer; -import org.springframework.cloud.sleuth.trace.TestSpanContextHolder; -import org.springframework.context.ApplicationEventPublisher; - import java.util.ArrayList; import java.util.List; import java.util.Queue; @@ -24,6 +9,22 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import lombok.SneakyThrows; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; +import org.springframework.cloud.sleuth.Tracer; +import org.springframework.cloud.sleuth.instrument.async.TraceableExecutorService; +import org.springframework.cloud.sleuth.sampler.AlwaysSampler; +import org.springframework.cloud.sleuth.trace.DefaultTracer; +import org.springframework.cloud.sleuth.trace.TestSpanContextHolder; +import org.springframework.context.ApplicationEventPublisher; + import static java.util.stream.Collectors.toList; import static org.assertj.core.api.BDDAssertions.then; @@ -55,7 +56,7 @@ public class TraceableExecutorServiceTests { @Test @SneakyThrows public void should_propagate_trace_id_and_set_new_span_when_traceable_executor_service_is_executed() { - Span span = this.tracer.startTrace("PARENT"); + Span span = this.tracer.startTrace(new SpanName("http", "PARENT")); CompletableFuture.allOf(runnablesExecutedViaTraceManagerableExecutorService()).get(); this.tracer.close(span); 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 d142fbbb9..d534e5f2c 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 @@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration; import org.springframework.cloud.sleuth.trace.TestSpanContextHolder; @@ -57,7 +58,7 @@ public class HystrixAnnotationsIntegrationTests { } private Span givenASpanInCurrentThread() { - Span span = this.tracer.startTrace("existing"); + Span span = this.tracer.startTrace(new SpanName("http", "existing")); this.tracer.continueSpan(span); return span; } @@ -111,11 +112,11 @@ public class HystrixAnnotationsIntegrationTests { return this.spanCaughtFromHystrixThread.get().getTraceId(); } - public String getSpanName() { + public SpanName getSpanName() { if (this.spanCaughtFromHystrixThread == null || (this.spanCaughtFromHystrixThread.get() != null - && this.spanCaughtFromHystrixThread.get() - .getName() == null)) { + && this.spanCaughtFromHystrixThread.get() + .getName() == null)) { return null; } return this.spanCaughtFromHystrixThread.get().getName(); 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 03c26e9dc..63ca1d9f4 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 @@ -1,9 +1,5 @@ package org.springframework.cloud.sleuth.instrument.hystrix; -import static com.netflix.hystrix.HystrixCommand.Setter.withGroupKey; -import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey; -import static org.assertj.core.api.BDDAssertions.then; - import java.util.Random; import org.junit.After; @@ -11,6 +7,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.trace.DefaultTracer; @@ -21,6 +18,10 @@ import com.netflix.hystrix.HystrixCommandProperties; import com.netflix.hystrix.HystrixThreadPoolProperties; import com.netflix.hystrix.strategy.HystrixPlugins; +import static com.netflix.hystrix.HystrixCommand.Setter.withGroupKey; +import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey; +import static org.assertj.core.api.BDDAssertions.then; + public class TraceCommandTests { static final long EXPECTED_TRACE_ID = 1L; @@ -63,7 +64,7 @@ public class TraceCommandTests { } private Span givenATraceIsPresentInTheCurrentThread() { - return this.tracer.joinTrace("test", + return this.tracer.joinTrace(new SpanName("http", "test"), Span.builder().traceId(EXPECTED_TRACE_ID).build()); } @@ -72,8 +73,8 @@ public class TraceCommandTests { withGroupKey(asKey("group")) .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties .Setter().withCoreSize(1).withMaxQueueSize(1)) - .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() - .withExecutionTimeoutEnabled(false))) { + .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() + .withExecutionTimeoutEnabled(false))) { @Override public Span doRun() throws Exception { return TestSpanContextHolder.getCurrentSpan(); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/SpanMessageHeadersTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/SpanMessageHeadersTests.java index 6e76a6233..4cffb2c2c 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/SpanMessageHeadersTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/SpanMessageHeadersTests.java @@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.instrument.TraceKeys; import org.springframework.messaging.Message; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; @@ -38,7 +39,7 @@ public class SpanMessageHeadersTests { @Test public void spanHeadersAdded() { - Span span = Span.builder().name("foo").spanId(1L).traceId(2L).build(); + Span span = Span.builder().name(new SpanName("http", "foo")).spanId(1L).traceId(2L).build(); Message message = new GenericMessage<>("Hello World"); message = SpanMessageHeaders.addSpanHeaders(this.traceKeys, message, span); assertThat(message.getHeaders()).containsKey(Span.SPAN_ID_NAME); @@ -46,7 +47,7 @@ public class SpanMessageHeadersTests { @Test public void nativeSpanHeadersAdded() { - Span span = Span.builder().name("foo").spanId(1L).traceId(2L).build(); + Span span = Span.builder().name(new SpanName("http", "foo")).spanId(1L).traceId(2L).build(); MessageHeaderAccessor accessor = SimpMessageHeaderAccessor.create(); Message message = MessageBuilder.createMessage("Hello World", accessor.getMessageHeaders()); message = SpanMessageHeaders.addSpanHeaders(this.traceKeys, message, span); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceChannelInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceChannelInterceptorTests.java index 0985d17a3..68e6c7807 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceChannelInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceChannelInterceptorTests.java @@ -16,12 +16,6 @@ package org.springframework.cloud.sleuth.instrument.messaging; -import static org.assertj.core.api.BDDAssertions.then; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - import java.util.ArrayList; import java.util.List; @@ -35,6 +29,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.IntegrationTest; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.event.SpanReleasedEvent; import org.springframework.cloud.sleuth.instrument.messaging.TraceChannelInterceptorTests.App; @@ -52,6 +47,12 @@ import org.springframework.messaging.MessagingException; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import static org.assertj.core.api.BDDAssertions.then; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + /** * @author Dave Syer */ @@ -138,7 +139,7 @@ public class TraceChannelInterceptorTests implements MessageHandler { @Test public void headerCreation() { - Span span = this.tracer.startTrace("testSendMessage", new AlwaysSampler()); + Span span = this.tracer.startTrace(new SpanName("http", "testSendMessage"), new AlwaysSampler()); this.channel.send(MessageBuilder.withPayload("hi").build()); this.tracer.close(span); assertNotNull("message was null", this.message); @@ -154,7 +155,7 @@ public class TraceChannelInterceptorTests implements MessageHandler { // TODO: Refactor to parametrized test together with sending messages via channel @Test public void headerCreationViaMessagingTemplate() { - Span span = this.tracer.startTrace("testSendMessage", new AlwaysSampler()); + Span span = this.tracer.startTrace(new SpanName("http", "testSendMessage"), new AlwaysSampler()); this.messagingTemplate.send(MessageBuilder.withPayload("hi").build()); this.tracer.close(span); assertNotNull("message was null", this.message); 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 4e27d0a10..023067431 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 @@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.IntegrationTest; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.messaging.TraceContextPropagationChannelInterceptorTests.App; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; @@ -65,7 +66,7 @@ public class TraceContextPropagationChannelInterceptorTests { @Test public void testSpanPropagation() { - Span span = this.tracer.startTrace("testSendMessage", new AlwaysSampler()); + Span span = this.tracer.startTrace(new SpanName("http", "testSendMessage"), new AlwaysSampler()); this.channel.send(MessageBuilder.withPayload("hi").build()); Long expectedSpanId = span.getSpanId(); this.tracer.close(span); 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 b4485d988..6631b9df3 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 @@ -1,13 +1,15 @@ package org.springframework.cloud.sleuth.instrument.web; -import com.jayway.awaitility.Awaitility; +import java.util.concurrent.atomic.AtomicReference; + import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration; import org.springframework.cloud.sleuth.trace.TestSpanContextHolder; @@ -17,7 +19,7 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import java.util.concurrent.atomic.AtomicReference; +import com.jayway.awaitility.Awaitility; import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then; @@ -39,7 +41,7 @@ public class TraceAsyncIntegrationTests { } private Span givenASpanInCurrentThread() { - Span span = this.tracer.startTrace("existing"); + Span span = this.tracer.startTrace(new SpanName("http", "existing")); this.tracer.continueSpan(span); return span; } @@ -55,6 +57,8 @@ public class TraceAsyncIntegrationTests { then(span) .hasTraceIdEqualTo(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getTraceId()) .hasNameNotEqualTo(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpanName()); + then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpanName()). + isEqualTo(SpanName.fromString("async:ClassPerformingAsyncLogic#method=invokeAsynchronousLogic")); } }); } @@ -92,7 +96,7 @@ public class TraceAsyncIntegrationTests { return this.span.get().getTraceId(); } - public String getSpanName() { + public SpanName getSpanName() { if (this.span.get() != null && this.span.get().getName() == null) { return null; } 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 7017cec7b..d4430c884 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 @@ -16,21 +16,15 @@ package org.springframework.cloud.sleuth.instrument.web; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.entry; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.mockito.MockitoAnnotations.initMocks; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; - import java.util.Random; +import lombok.SneakyThrows; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.springframework.cloud.sleuth.Sampler; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.TraceKeys; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; @@ -46,7 +40,13 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import lombok.SneakyThrows; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.mockito.MockitoAnnotations.initMocks; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; /** * @author Spencer Gibb @@ -113,8 +113,7 @@ public class TraceFilterTests { @Test public void continuesSpanInRequestAttr() throws Exception { - - Span span = this.tracer.startTrace("foo"); + Span span = this.tracer.startTrace(new SpanName("http", "foo")); this.request.setAttribute(TraceFilter.TRACE_REQUEST_ATTR, span); // It should have been removed from the thread local context so simulate that TestSpanContextHolder.removeCurrentSpan(); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/multiple/MultipleHopsIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/multiple/MultipleHopsIntegrationTests.java index 93012a35e..d66dbfc9a 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/multiple/MultipleHopsIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/multiple/MultipleHopsIntegrationTests.java @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.sleuth.Sampler; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.event.ArrayListSpanAccumulator; import org.springframework.cloud.sleuth.instrument.TraceKeys; @@ -44,9 +45,11 @@ public class MultipleHopsIntegrationTests extends AbstractMvcIntegrationTest { MockMvcResultMatchers.status().isOk()); await().until(() -> { - then(this.arrayListSpanAccumulator.getSpans().stream().map(Span::getName).collect( - toList())).containsAll(asList("http/greeting", "message/greetings", - "message/words", "message/counts")); + then(this.arrayListSpanAccumulator.getSpans().stream().map(Span::getName) + .map(SpanName::toString) + .collect( + toList())).containsAll(asList("http:/greeting", "message:greetings", + "message:words", "message:counts")); }); } 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 18b8a2f2e..8f24e0ace 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 @@ -16,22 +16,22 @@ package org.springframework.cloud.sleuth.instrument.zuul; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.verify; - import java.util.Random; +import com.netflix.zuul.context.RequestContext; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.event.ClientReceivedEvent; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.trace.DefaultTracer; import org.springframework.cloud.sleuth.trace.TestSpanContextHolder; import org.springframework.context.ApplicationEventPublisher; -import com.netflix.zuul.context.RequestContext; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.verify; /** * @author Dave Syer @@ -55,7 +55,7 @@ public class TracePostZuulFilterTests { @Test public void filterPublishesEvent() throws Exception { this.filter.setApplicationEventPublisher(this.publisher); - this.tracer.startTrace("start"); + this.tracer.startTrace(new SpanName("http", "start")); this.filter.run(); verify(this.publisher).publishEvent(isA(ClientReceivedEvent.class)); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilterTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilterTests.java index b3df1f7fb..ac00525a6 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilterTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilterTests.java @@ -16,25 +16,25 @@ package org.springframework.cloud.sleuth.instrument.zuul; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; - import java.util.Random; +import com.netflix.zuul.context.RequestContext; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.sampler.NeverSampler; import org.springframework.cloud.sleuth.trace.DefaultTracer; import org.springframework.cloud.sleuth.trace.TestSpanContextHolder; import org.springframework.context.ApplicationEventPublisher; -import com.netflix.zuul.context.RequestContext; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; /** * @author Dave Syer @@ -59,7 +59,7 @@ public class TracePreZuulFilterTests { @Test public void filterAddsHeaders() throws Exception { - this.tracer.startTrace("start"); + this.tracer.startTrace(new SpanName("http", "start")); this.filter.run(); RequestContext ctx = RequestContext.getCurrentContext(); assertThat(ctx.getZuulRequestHeaders().get(Span.TRACE_ID_NAME), @@ -70,7 +70,7 @@ public class TracePreZuulFilterTests { @Test public void notSampledIfNotExportable() throws Exception { - this.tracer.startTrace("start", NeverSampler.INSTANCE); + this.tracer.startTrace(new SpanName("http", "start"), NeverSampler.INSTANCE); this.filter.run(); RequestContext ctx = RequestContext.getCurrentContext(); assertThat(ctx.getZuulRequestHeaders().get(Span.TRACE_ID_NAME), diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTracerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTracerTests.java index 8a2b55c8e..944150fd2 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTracerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/trace/DefaultTracerTests.java @@ -16,15 +16,6 @@ package org.springframework.cloud.sleuth.trace; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -34,6 +25,7 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.event.SpanAcquiredEvent; import org.springframework.cloud.sleuth.event.SpanReleasedEvent; @@ -42,14 +34,25 @@ import org.springframework.cloud.sleuth.sampler.NeverSampler; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + /** * @author Spencer Gibb */ public class DefaultTracerTests { - public static final String CREATE_SIMPLE_TRACE = "createSimpleTrace"; - public static final String IMPORTANT_WORK_1 = "important work 1"; - public static final String IMPORTANT_WORK_2 = "important work 2"; + public static final String CREATE_SIMPLE_TRACE_SPAN_NAME = "createSimpleTrace"; + public static final SpanName CREATE_SIMPLE_TRACE = new SpanName("http", + CREATE_SIMPLE_TRACE_SPAN_NAME); + public static final SpanName IMPORTANT_WORK_1 = new SpanName("http", "important work 1"); + public static final SpanName IMPORTANT_WORK_2 = new SpanName("http", "important work 2"); public static final int NUM_SPANS = 3; private ApplicationEventPublisher publisher; @@ -126,7 +129,7 @@ public class DefaultTracerTests { this.publisher); Span span = tracer.startTrace(CREATE_SIMPLE_TRACE, NeverSampler.INSTANCE); assertThat(span.isExportable(), is(false)); - Span child = tracer.joinTrace(CREATE_SIMPLE_TRACE + "/child", span); + Span child = tracer.joinTrace(new SpanName("http", CREATE_SIMPLE_TRACE_SPAN_NAME + "/child"), span); assertThat(child.isExportable(), is(false)); } @@ -163,7 +166,7 @@ public class DefaultTracerTests { assertThat(tracer.getCurrentSpan(), is(equalTo(grandParent))); } - private Span assertSpan(List spans, Long parentId, String name) { + private Span assertSpan(List spans, Long parentId, SpanName name) { List found = findSpans(spans, parentId); assertThat("more than one span with parentId " + parentId, found.size(), is(1)); Span span = found.get(0); 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 e0f48e6ab..64d571663 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 @@ -21,7 +21,6 @@ import java.util.Optional; import java.util.Random; import java.util.stream.Collectors; -import integration.MessagingApplicationTests.IntegrationSpanCollectorConfig; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,6 +32,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import integration.MessagingApplicationTests.IntegrationSpanCollectorConfig; import sample.SampleMessagingApplication; import tools.AbstractIntegrationTest; import zipkin.Constants; @@ -116,7 +117,7 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { private Optional findLastHttpSpan() { return this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> "http/foo".equals(span.name)).findFirst(); + .filter(span -> "http:/foo".equals(span.name)).findFirst(); } private Optional findSpanWithAnnotation(List eventSpans, String annotationName) { @@ -128,13 +129,13 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { private List findAllEventRelatedSpans() { return this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> "message/messages".equals(span.name) && span.parentId != null).collect( + .filter(span -> "message:messages".equals(span.name) && span.parentId != null).collect( Collectors.toList()); } private Optional findFirstHttpRequestSpan() { return this.integrationTestSpanCollector.hashedSpans.stream() - .filter(span -> "http/".equals(span.name) && span.parentId != null).findFirst(); + .filter(span -> "http:/".equals(span.name) && span.parentId != null).findFirst(); } private void thenAllSpansArePresent(Optional firstHttpSpan, diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-stream/src/main/java/sample/SampleController.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-stream/src/main/java/sample/SampleController.java index aaee6f6e8..bd912393a 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-stream/src/main/java/sample/SampleController.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-stream/src/main/java/sample/SampleController.java @@ -16,12 +16,16 @@ package sample; +import java.util.Random; +import java.util.concurrent.Callable; + import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.SpanAccessor; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.context.ApplicationListener; @@ -29,9 +33,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; -import java.util.Random; -import java.util.concurrent.Callable; - /** * @author Spencer Gibb */ @@ -93,7 +94,7 @@ ApplicationListener { @SneakyThrows @RequestMapping("/traced") public String traced() { - Span span = this.tracer.startTrace("customTraceEndpoint", + Span span = this.tracer.startTrace(new SpanName("http", "customTraceEndpoint"), new AlwaysSampler()); int millis = this.random.nextInt(1000); log.info("Sleeping for {} millis", millis); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/test/java/integration/ZipkinStreamTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/test/java/integration/ZipkinStreamTests.java index c2a2e7a52..4392b0eb5 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/test/java/integration/ZipkinStreamTests.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/test/java/integration/ZipkinStreamTests.java @@ -15,6 +15,9 @@ */ package integration; +import java.util.Collections; +import java.util.Random; + import example.ZipkinStreamServerApplication; import org.junit.Before; import org.junit.Test; @@ -25,6 +28,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.boot.test.WebIntegrationTest; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.stream.Host; import org.springframework.cloud.sleuth.stream.SleuthSink; import org.springframework.cloud.sleuth.stream.Spans; @@ -36,9 +40,6 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import tools.AbstractIntegrationTest; -import java.util.Collections; -import java.util.Random; - @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { TestSupportBinderAutoConfiguration.class, ZipkinStreamServerApplication.class }) @@ -62,7 +63,7 @@ public class ZipkinStreamTests extends AbstractIntegrationTest { @Test public void should_propagate_spans_to_zipkin() { - Span span = Span.builder().traceId(this.traceId).spanId(this.spanId).name("test").build(); + Span span = Span.builder().traceId(this.traceId).spanId(this.spanId).name(new SpanName("http", "test")).build(); span.tag(getRequiredBinaryAnnotationName(), "10131"); this.input.send(messageWithSpan(span)); 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 761ad7b9a..21aa5fa66 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 @@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.SpanAccessor; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.context.ApplicationListener; @@ -96,7 +97,7 @@ ApplicationListener { @SneakyThrows @RequestMapping("/traced") public String traced() { - Span span = this.tracer.startTrace("customTraceEndpoint", + Span span = this.tracer.startTrace(new SpanName("http", "customTraceEndpoint"), new AlwaysSampler()); int millis = this.random.nextInt(1000); log.info("Sleeping for {} millis", millis); 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 aaee6f6e8..bd912393a 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 @@ -16,12 +16,16 @@ package sample; +import java.util.Random; +import java.util.concurrent.Callable; + import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.SpanAccessor; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.context.ApplicationListener; @@ -29,9 +33,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; -import java.util.Random; -import java.util.concurrent.Callable; - /** * @author Spencer Gibb */ @@ -93,7 +94,7 @@ ApplicationListener { @SneakyThrows @RequestMapping("/traced") public String traced() { - Span span = this.tracer.startTrace("customTraceEndpoint", + Span span = this.tracer.startTrace(new SpanName("http", "customTraceEndpoint"), new AlwaysSampler()); int millis = this.random.nextInt(1000); log.info("Sleeping for {} millis", millis); diff --git a/spring-cloud-sleuth-stream/src/test/java/org/springframework/cloud/sleuth/stream/ServerPropertiesHostLocatorTests.java b/spring-cloud-sleuth-stream/src/test/java/org/springframework/cloud/sleuth/stream/ServerPropertiesHostLocatorTests.java index 5df789568..a2c1ef257 100644 --- a/spring-cloud-sleuth-stream/src/test/java/org/springframework/cloud/sleuth/stream/ServerPropertiesHostLocatorTests.java +++ b/spring-cloud-sleuth-stream/src/test/java/org/springframework/cloud/sleuth/stream/ServerPropertiesHostLocatorTests.java @@ -16,18 +16,19 @@ package org.springframework.cloud.sleuth.stream; -import org.junit.Test; -import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.cloud.sleuth.Span; - import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Collections; +import org.junit.Test; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; + import static org.assertj.core.api.Assertions.assertThat; public class ServerPropertiesHostLocatorTests { - Span span = new Span(1, 3, "name", 1L, Collections.emptyList(), 2L, true, true, + Span span = new Span(1, 3, new SpanName("http", "name"), 1L, Collections.emptyList(), 2L, true, true, "process"); @Test diff --git a/spring-cloud-sleuth-stream/src/test/java/org/springframework/cloud/sleuth/stream/StreamSpanListenerTests.java b/spring-cloud-sleuth-stream/src/test/java/org/springframework/cloud/sleuth/stream/StreamSpanListenerTests.java index efb75792e..1529e8def 100644 --- a/spring-cloud-sleuth-stream/src/test/java/org/springframework/cloud/sleuth/stream/StreamSpanListenerTests.java +++ b/spring-cloud-sleuth-stream/src/test/java/org/springframework/cloud/sleuth/stream/StreamSpanListenerTests.java @@ -35,6 +35,7 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.cloud.sleuth.Sampler; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.cloud.sleuth.event.ClientReceivedEvent; @@ -75,16 +76,16 @@ public class StreamSpanListenerTests { @Test public void acquireAndRelease() { - Span context = this.tracer.startTrace("foo"); + Span context = this.tracer.startTrace(new SpanName("http", "foo")); this.tracer.close(context); assertEquals(1, this.test.spans.size()); } @Test public void rpcAnnotations() { - Span parent = Span.builder().traceId(1L).name("parent").remote(true) + Span parent = Span.builder().traceId(1L).name(new SpanName("http", "parent")).remote(true) .build(); - Span context = this.tracer.joinTrace("child", parent); + Span context = this.tracer.joinTrace(new SpanName("http", "child"), parent); this.application.publishEvent(new ClientSentEvent(this, context)); this.application .publishEvent(new ServerReceivedEvent(this, parent, context)); @@ -107,7 +108,7 @@ public class StreamSpanListenerTests { @Test public void shouldIncreaseNumberOfAcceptedSpans() { - Span context = this.tracer.startTrace("foo"); + Span context = this.tracer.startTrace(new SpanName("http", "foo")); this.tracer.close(context); this.listener.poll(); diff --git a/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIterator.java b/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIterator.java index a2efae68e..b30284f15 100644 --- a/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIterator.java +++ b/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIterator.java @@ -18,13 +18,12 @@ package org.springframework.cloud.sleuth.zipkin.stream; import java.util.Iterator; import java.util.NoSuchElementException; +import lombok.extern.apachecommons.CommonsLog; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.stream.Host; import org.springframework.cloud.sleuth.stream.SleuthSink; import org.springframework.cloud.sleuth.stream.Spans; -import org.springframework.util.StringUtils; - -import lombok.extern.apachecommons.CommonsLog; import zipkin.BinaryAnnotation; import zipkin.Constants; import zipkin.Endpoint; @@ -37,6 +36,8 @@ import zipkin.Span.Builder; @CommonsLog final class SamplingZipkinSpanIterator implements Iterator { + private static final String MESSAGE_COMPONENT = "message"; + private final Sampler sampler; private final Iterator delegate; private final Host host; @@ -75,7 +76,7 @@ final class SamplingZipkinSpanIterator implements Iterator { * returns a converted span or null if it is invalid or unsampled. */ zipkin.Span convertAndSample(Span input, Host host) { - if (!input.getName().equals("message/" + SleuthSink.INPUT)) { + if (!protocolWithAddressMatch(input)) { zipkin.Span result = SamplingZipkinSpanIterator.convert(input, host); if (this.sampler.isSampled(result.traceId)) { return result; @@ -87,6 +88,12 @@ final class SamplingZipkinSpanIterator implements Iterator { return null; } + private boolean protocolWithAddressMatch(Span input) { + SpanName spanName = input.getName(); + return SamplingZipkinSpanIterator.MESSAGE_COMPONENT.equals(spanName.component) && + ("/" + SleuthSink.INPUT).equals(spanName.address); + } + /** * Converts a given Sleuth span to a Zipkin Span. *
      @@ -128,8 +135,8 @@ final class SamplingZipkinSpanIterator implements Iterator { zipkinSpan.parentId(span.getParents().get(0)); } zipkinSpan.id(span.getSpanId()); - if (StringUtils.hasText(span.getName())) { - zipkinSpan.name(span.getName()); + if (!SpanName.NO_NAME.equals(span.getName())) { + zipkinSpan.name(span.getName().toString()); } return zipkinSpan.build(); } diff --git a/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIteratorTests.java b/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIteratorTests.java index a6aa3dcfd..57f52633a 100644 --- a/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIteratorTests.java +++ b/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/SamplingZipkinSpanIteratorTests.java @@ -15,18 +15,19 @@ */ package org.springframework.cloud.sleuth.zipkin.stream; -import org.junit.Test; -import org.springframework.cloud.sleuth.Span; -import org.springframework.cloud.sleuth.stream.Host; -import org.springframework.cloud.sleuth.stream.Spans; -import zipkin.Sampler; - import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; +import org.junit.Test; +import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; +import org.springframework.cloud.sleuth.stream.Host; +import org.springframework.cloud.sleuth.stream.Spans; +import zipkin.Sampler; + import static org.assertj.core.api.Assertions.assertThat; public class SamplingZipkinSpanIteratorTests { @@ -36,7 +37,7 @@ public class SamplingZipkinSpanIteratorTests { @Test public void skipsInputSpans() { Spans spans = new Spans(this.host, - Collections.singletonList(span("message/sleuth"))); + Collections.singletonList(span("sleuth"))); Iterator result = new SamplingZipkinSpanIterator( Sampler.create(1.0f), spans); @@ -52,7 +53,8 @@ public class SamplingZipkinSpanIteratorTests { Iterator result = new SamplingZipkinSpanIterator( Sampler.create(1.0f), spans); - assertThat(result).extracting(s -> s.name).containsExactly("foo", "bar", "baz"); + assertThat(result).extracting(s -> s.name).containsExactly( + "message:/foo", "message:/bar", "message:/baz"); } @Test @@ -71,12 +73,13 @@ public class SamplingZipkinSpanIteratorTests { Iterator result = new SamplingZipkinSpanIterator(everyOtherSampler, spans); - assertThat(result).extracting(s -> s.name).containsExactly("foo", "baz"); + assertThat(result).extracting(s -> s.name).containsExactly( + "message:/foo", "message:/baz"); } Span span(String name) { Long id = new Random().nextLong(); - return new Span(1, 3, name, id, Collections.emptyList(), id, true, true, + return new Span(1, 3, new SpanName("message", "/" + name), id, Collections.emptyList(), id, true, true, "process"); } } \ No newline at end of file diff --git a/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListenerTests.java b/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListenerTests.java index 47c900b7a..9586d5833 100644 --- a/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListenerTests.java +++ b/spring-cloud-sleuth-zipkin-stream/src/test/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListenerTests.java @@ -17,6 +17,8 @@ package org.springframework.cloud.sleuth.zipkin.stream; import java.util.Collections; + +import org.springframework.cloud.sleuth.SpanName; import zipkin.BinaryAnnotation; import zipkin.Endpoint; @@ -27,7 +29,7 @@ import org.springframework.cloud.sleuth.stream.Host; import static org.assertj.core.api.Assertions.assertThat; public class ZipkinMessageListenerTests { - Span span = new Span(1, 3, "name", 1L, Collections.emptyList(), 2L, true, true, + Span span = new Span(1, 3, new SpanName("http", "name"), 1L, Collections.emptyList(), 2L, true, true, "process"); Host host = new Host("myservice", "1.2.3.4", 8080); Endpoint endpoint = Endpoint.create("myservice", 1 << 24 | 2 << 16 | 3 << 8 | 4, 8080); @@ -80,7 +82,7 @@ public class ZipkinMessageListenerTests { // TODO: "unknown" bc process id, documented as not nullable, is null in some tests. @Test public void nullProcessIdCoercesToUnknownServiceName() { - Span noProcessId = Span.builder().traceId(1L).name("parent").remote(true).build(); + Span noProcessId = Span.builder().traceId(1L).name(new SpanName("http", "parent")).remote(true).build(); zipkin.Span result = SamplingZipkinSpanIterator.convert(noProcessId, this.host); diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListener.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListener.java index 65d19e78b..da07d4953 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListener.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListener.java @@ -19,8 +19,10 @@ package org.springframework.cloud.sleuth.zipkin; import java.nio.charset.Charset; import java.util.Map; +import lombok.extern.apachecommons.CommonsLog; import org.springframework.cloud.sleuth.Log; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.event.ClientReceivedEvent; import org.springframework.cloud.sleuth.event.ClientSentEvent; import org.springframework.cloud.sleuth.event.ServerReceivedEvent; @@ -29,9 +31,6 @@ import org.springframework.cloud.sleuth.event.SpanAcquiredEvent; import org.springframework.cloud.sleuth.event.SpanReleasedEvent; import org.springframework.context.event.EventListener; import org.springframework.core.annotation.Order; -import org.springframework.util.StringUtils; - -import lombok.extern.apachecommons.CommonsLog; import zipkin.Annotation; import zipkin.BinaryAnnotation; import zipkin.Constants; @@ -150,8 +149,8 @@ public class ZipkinSpanListener { zipkinSpan.parentId(span.getParents().get(0)); } zipkinSpan.id(span.getSpanId()); - if (StringUtils.hasText(span.getName())) { - zipkinSpan.name(span.getName()); + if (!SpanName.NO_NAME.equals(span.getName())) { + zipkinSpan.name(span.getName().toString()); } return zipkinSpan.build(); } diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListenerTests.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListenerTests.java index c5bb4143c..6aaab71f0 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListenerTests.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListenerTests.java @@ -16,14 +16,10 @@ package org.springframework.cloud.sleuth.zipkin; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; - +import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; -import javax.annotation.PostConstruct; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -31,6 +27,7 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.cloud.sleuth.Sampler; import org.springframework.cloud.sleuth.Span; +import org.springframework.cloud.sleuth.SpanName; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.cloud.sleuth.event.ClientReceivedEvent; @@ -45,6 +42,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; + /** * @author Dave Syer * @@ -70,7 +70,7 @@ public class ZipkinSpanListenerTests { this.test.spans.clear(); } - Span parent = Span.builder().traceId(1L).name("parent").remote(true).build(); + Span parent = Span.builder().traceId(1L).name(new SpanName("http", "parent")).remote(true).build(); /** Sleuth timestamps are millisecond granularity while zipkin is microsecond. */ @Test @@ -118,7 +118,7 @@ public class ZipkinSpanListenerTests { */ @Test public void spanWithoutAnnotationsLogsComponent() { - Span context = this.tracer.startTrace("foo"); + Span context = this.tracer.startTrace(new SpanName("http", "foo")); this.tracer.close(context); assertEquals(1, this.test.spans.size()); assertThat(this.test.spans.get(0).binaryAnnotations.get(0).endpoint.serviceName) @@ -127,7 +127,7 @@ public class ZipkinSpanListenerTests { @Test public void rpcAnnotations() { - Span context = this.tracer.joinTrace("child", this.parent); + Span context = this.tracer.joinTrace(new SpanName("http", "child"), this.parent); this.application.publishEvent(new ClientSentEvent(this, context)); this.application.publishEvent(new ServerReceivedEvent(this, this.parent, context)); this.application.publishEvent(new ServerSentEvent(this, this.parent, context));