From 82ed9f78a16ef34db48979762e7bec606d20ff9c Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Mon, 18 Jan 2016 14:38:09 +0100 Subject: [PATCH] [#106] Converted UUID to Long - Changed Random instantiation to a shared Random - Changed the name of the converter - Changed generator into random - Span id is now non-nullable. - it gets generated in the http filter if it's not there - it's generated in the spring-integration channels if it wasn't set --- .../cloud/sleuth/MilliSpan.java | 13 +- .../springframework/cloud/sleuth/Span.java | 33 ++++- .../autoconfig/TraceAutoConfiguration.java | 21 +-- .../AbstractTraceChannelInterceptor.java | 63 +++++---- .../integration/SpanMessageHeaders.java | 14 +- .../integration/StompMessageBuilder.java | 11 +- .../integration/TraceChannelInterceptor.java | 6 +- ...eContextPropagationChannelInterceptor.java | 20 +-- ...aceSpringIntegrationAutoConfiguration.java | 10 +- .../TraceStompMessageChannelInterceptor.java | 6 +- .../sleuth/instrument/web/TraceFilter.java | 36 ++++-- .../web/TraceWebAutoConfiguration.java | 5 +- .../TraceFeignClientAutoConfiguration.java | 58 ++++----- .../client/TraceRestTemplateInterceptor.java | 22 ++-- .../instrument/zuul/TracePreZuulFilter.java | 19 ++- .../TraceRestClientRibbonCommandFactory.java | 26 ++-- .../cloud/sleuth/log/Slf4jSpanListener.java | 10 +- .../sampler/DefaultStringToUuidConverter.java | 44 ------- .../sampler/PercentageBasedSampler.java | 12 +- .../UuidTraceIdToThresholdComparable.java | 68 ---------- .../sleuth/trace/DefaultTraceManager.java | 20 +-- .../sleuth/DefaultTraceManagerTests.java | 14 +- .../cloud/sleuth/MilliSpanTests.java | 8 +- .../cloud/sleuth/SpanTest.java | 34 +++++ .../cloud/sleuth/assertions/SpanAssert.java | 50 +++---- .../sleuth/instrument/TraceCallableTests.java | 16 +-- .../sleuth/instrument/TraceRunnableTests.java | 14 +- .../TraceableExecutorServiceTests.java | 9 +- ...HystrixViaAnnotationsIntegrationTests.java | 6 +- .../instrument/hystrix/TraceCommandTests.java | 18 +-- .../AbstractTraceStompIntegrationTests.java | 16 +-- .../TraceChannelInterceptorTests.java | 22 ++-- ...extPropagationChannelInterceptorTests.java | 13 +- ...ceStompMessageChannelInterceptorTests.java | 6 +- ...extPropagationChannelInterceptorTests.java | 4 +- ...stTemplateTraceAspectIntegrationTests.java | 2 +- .../web/TraceAsyncIntegrationTests.java | 21 ++- .../web/TraceFilterIntegartionTests.java | 74 ----------- .../web/TraceFilterIntegrationTests.java | 122 ++++++++---------- .../TraceFilterMockChainIntegrationTests.java | 88 +++++++++++++ .../instrument/web/TraceFilterTests.java | 23 ++-- .../web/client/FeignTraceTests.java | 30 ++--- .../TraceRestTemplateInterceptorTests.java | 25 ++-- .../sleuth/log/JsonLogSpanListenerTests.java | 6 +- .../DefaultStringToUuidConverterTests.java | 31 ----- .../sampler/PercentageBasedSamplerTests.java | 36 ++---- ...UuidTraceIdToThresholdComparableTests.java | 53 -------- .../sleuth/template/TraceTemplateTests.java | 6 +- .../main/java/sample/SampleBackground.java | 3 +- .../MessagingApplicationTests.java | 10 +- .../main/java/sample/SampleController.java | 8 +- .../main/java/sample/SampleController.java | 16 +-- .../java/tools/AbstractIntegrationTest.java | 59 +++------ .../java/tools/RequestSendingRunnable.java | 9 +- .../java/integration/ZipkinStreamTests.java | 15 +-- .../main/java/sample/SampleBackground.java | 8 +- .../main/java/sample/SampleController.java | 16 +-- .../test/java/integration/ZipkinTests.java | 6 +- .../main/java/sample/SampleBackground.java | 8 +- .../main/java/sample/SampleController.java | 16 +-- .../stream/ServerPropertiesHostLocator.java | 4 +- .../ServerPropertiesHostLocatorTests.java | 9 +- .../stream/StreamSpanListenerTests.java | 2 +- .../zipkin/stream/ZipkinMessageListener.java | 57 +++----- .../SamplingZipkinSpanIteratorTests.java | 15 ++- .../stream/ZipkinMessageListenerTests.java | 8 +- .../sleuth/zipkin/ZipkinSpanListener.java | 38 ++---- .../zipkin/ZipkinSpanListenerTests.java | 2 +- 68 files changed, 685 insertions(+), 888 deletions(-) delete mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/DefaultStringToUuidConverter.java delete mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/UuidTraceIdToThresholdComparable.java create mode 100644 spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java delete mode 100644 spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegartionTests.java create mode 100644 spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterMockChainIntegrationTests.java delete mode 100644 spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/DefaultStringToUuidConverterTests.java delete mode 100644 spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/UuidTraceIdToThresholdComparableTests.java diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java index 60dd3db30..95a2ba02d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java @@ -35,10 +35,10 @@ public class MilliSpan implements Span { private final long begin; private long end = 0; private final String name; - private final String traceId; + private final long traceId; @Singular - private List parents = new ArrayList<>(); - private final String spanId; + private List parents = new ArrayList<>(); + private final long spanId; private boolean remote = false; private boolean exportable = true; private final Map tags = new LinkedHashMap<>(); @@ -50,7 +50,7 @@ public class MilliSpan implements Span { return new MilliSpan().toBuilder(); } - public MilliSpan(long begin, long end, String name, String traceId, List parents, String spanId, boolean remote, boolean exportable, String processId) { + public MilliSpan(long begin, long end, String name, long traceId, List parents, long spanId, boolean remote, boolean exportable, String processId) { this.begin = begin<=0 ? System.currentTimeMillis() : begin; this.end = end; this.name = name; @@ -66,9 +66,10 @@ public class MilliSpan implements Span { private MilliSpan() { this.begin = 0; this.name = null; - this.traceId = null; - this.spanId = null; + this.traceId = 0; + this.spanId = 0; this.processId = null; + this.parents = new ArrayList<>(); } @Override 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 eb6ab279a..42aefcbb3 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 @@ -16,6 +16,9 @@ package org.springframework.cloud.sleuth; +import org.springframework.util.Assert; + +import java.math.BigInteger; import java.util.List; import java.util.Map; @@ -41,18 +44,18 @@ public interface Span { * The spanId is immutable and cannot be changed. It is safe to access this from * multiple threads. */ - String getSpanId(); + long getSpanId(); /** * A pseudo-unique (random) number assigned to the trace associated with this span */ - String getTraceId(); + long getTraceId(); /** * Return a unique id for the process from which this Span originated. *

*

- * Will never be null. + * // TODO: Check when this is going to be null (cause it may be null) */ String getProcessId(); @@ -62,7 +65,7 @@ public interface Span { *

* The collection will be empty if there are no parents. */ - List getParents(); + List getParents(); /** * Flag that tells us whether the span was started in another process. Useful in RPC @@ -127,4 +130,26 @@ public interface Span { * Will never be null. */ List logs(); + + + /** + * Class used for conversions of long ids to their String representation + */ + class IdConverter { + + /** + * Represents given long id as hex string + */ + public static String toHex(long id) { + return Long.toHexString(id); + } + + /** + * Represents hex string as long + */ + public static long fromHex(String hexString) { + Assert.hasText(hexString, "Can't convert empty hex string to long"); + return new BigInteger(hexString, 16).longValue(); + } + } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java index 79a1fdda9..fd051f6e3 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java @@ -19,15 +19,13 @@ package org.springframework.cloud.sleuth.autoconfig; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.sleuth.Sampler; -import org.springframework.cloud.sleuth.sampler.DefaultStringToUuidConverter; import org.springframework.cloud.sleuth.sampler.IsTracingSampler; -import org.springframework.cloud.sleuth.sampler.StringToUuidConverter; import org.springframework.cloud.sleuth.trace.DefaultTraceManager; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.util.IdGenerator; -import org.springframework.util.JdkIdGenerator; + +import java.util.Random; /** * @author Spencer Gibb @@ -37,9 +35,8 @@ import org.springframework.util.JdkIdGenerator; public class TraceAutoConfiguration { @Bean - @ConditionalOnMissingBean - public IdGenerator traceIdGenerator() { - return new JdkIdGenerator(); + public Random random() { + return new Random(); } @Bean @@ -50,14 +47,8 @@ public class TraceAutoConfiguration { @Bean @ConditionalOnMissingBean - public StringToUuidConverter stringToUuidConverter() { - return new DefaultStringToUuidConverter(); - } - - @Bean - @ConditionalOnMissingBean - public DefaultTraceManager traceManager(Sampler sampler, IdGenerator idGenerator, + public DefaultTraceManager traceManager(Sampler sampler, ApplicationEventPublisher publisher) { - return new DefaultTraceManager(sampler, idGenerator, publisher); + return new DefaultTraceManager(sampler, random(), publisher); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/AbstractTraceChannelInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/AbstractTraceChannelInterceptor.java index 16c576774..42d7e121b 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/AbstractTraceChannelInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/AbstractTraceChannelInterceptor.java @@ -9,7 +9,8 @@ import org.springframework.integration.context.IntegrationObjectSupport; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.support.ChannelInterceptorAdapter; -import org.springframework.util.StringUtils; + +import java.util.Random; /** * Abstraction over classes related to channel intercepting @@ -20,8 +21,11 @@ abstract class AbstractTraceChannelInterceptor extends ChannelInterceptorAdapter protected final TraceManager traceManager; - protected AbstractTraceChannelInterceptor(TraceManager traceManager) { + protected final Random random; + + protected AbstractTraceChannelInterceptor(TraceManager traceManager, Random random) { this.traceManager = traceManager; + this.random = random; } /** @@ -29,33 +33,42 @@ abstract class AbstractTraceChannelInterceptor extends ChannelInterceptorAdapter * trace id passed initially. */ Span buildSpan(Message message) { - String spanId = getHeader(message, Trace.SPAN_ID_NAME); - String traceId = getHeader(message, Trace.TRACE_ID_NAME); - if (StringUtils.hasText(traceId)) { - MilliSpan.MilliSpanBuilder span = MilliSpan.builder().traceId(traceId).spanId(spanId); - String parentId = getHeader(message, Trace.PARENT_ID_NAME); - if (message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) { - span.exportable(false); - } - String processId = getHeader(message, Trace.PROCESS_ID_NAME); - String spanName = getHeader(message, Trace.SPAN_NAME_NAME); - if (spanName != null) { - span.name(spanName); - } - if (processId != null) { - span.processId(processId); - } - if (parentId != null) { - span.parent(parentId); - } - span.remote(true); - return span.build(); + if (!hasHeader(message, Trace.TRACE_ID_NAME) || !hasHeader(message, Trace.SPAN_ID_NAME)) { + return null; // cannot build a span without ids } - return null; + long spanId = hasHeader(message, Trace.SPAN_ID_NAME) ? + getHeader(message, Trace.SPAN_ID_NAME, Long.class) : random.nextLong(); + long traceId = getHeader(message, Trace.TRACE_ID_NAME, Long.class); + MilliSpan.MilliSpanBuilder span = MilliSpan.builder().traceId(traceId).spanId(spanId); + Long parentId = getHeader(message, Trace.PARENT_ID_NAME, Long.class); + if (message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) { + span.exportable(false); + } + String processId = getHeader(message, Trace.PROCESS_ID_NAME); + String spanName = getHeader(message, Trace.SPAN_NAME_NAME); + if (spanName != null) { + span.name(spanName); + } + if (processId != null) { + span.processId(processId); + } + if (parentId != null) { + span.parent(parentId); + } + span.remote(true); + return span.build(); } String getHeader(Message message, String name) { - return (String) message.getHeaders().get(name); + return getHeader(message, name, String.class); + } + + T getHeader(Message message, String name, Class type) { + return message.getHeaders().get(name, type); + } + + boolean hasHeader(Message message, String name) { + return message.getHeaders().containsKey(name); } String getChannelName(MessageChannel channel) { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/SpanMessageHeaders.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/SpanMessageHeaders.java index bba242e01..dbdf24586 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/SpanMessageHeaders.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/SpanMessageHeaders.java @@ -20,6 +20,7 @@ import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.Message; +import org.springframework.util.StringUtils; import java.util.HashMap; import java.util.List; @@ -88,13 +89,20 @@ public class SpanMessageHeaders { private static void addHeader(Map headers, String name, String value) { - if (value != null) { + if (StringUtils.hasText(value)) { headers.put(name, value); } } - private static String getFirst(List parents) { - return parents == null || parents.isEmpty() ? null : parents.get(0); + private static void addHeader(Map headers, String name, + Long value) { + if (value != null) { + addHeader(headers, name, Span.IdConverter.toHex(value)); + } + } + + private static Long getFirst(List parents) { + return parents.isEmpty() ? null : parents.get(0); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/StompMessageBuilder.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/StompMessageBuilder.java index 5cb19c502..5b2eb4dd2 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/StompMessageBuilder.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/StompMessageBuilder.java @@ -22,6 +22,7 @@ import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.messaging.Message; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessageType; +import org.springframework.util.StringUtils; import java.util.List; import java.util.Map; @@ -64,12 +65,12 @@ public class StompMessageBuilder { setHeaderIfAbsent(Trace.SPAN_ID_NAME, span.getSpanId()); setHeaderIfAbsent(Trace.TRACE_ID_NAME, span.getTraceId()); setHeaderIfAbsent(Trace.SPAN_NAME_NAME, span.getName()); - String parentId = getParentId(TraceContextHolder.getCurrentSpan()); + Long parentId = getParentId(TraceContextHolder.getCurrentSpan()); if (parentId != null) setHeaderIfAbsent(Trace.PARENT_ID_NAME, parentId); String processId = span.getProcessId(); - if (processId != null) + if (StringUtils.hasText(processId)) setHeaderIfAbsent(Trace.PROCESS_ID_NAME, processId); } return this; @@ -113,8 +114,8 @@ public class StompMessageBuilder { } } - private String getParentId(final Span currentSpan) { - List parents = currentSpan.getParents(); - return parents == null || parents.isEmpty() ? null : parents.get(0); + private Long getParentId(final Span currentSpan) { + List parents = currentSpan.getParents(); + return parents.isEmpty() ? null : parents.get(0); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceChannelInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceChannelInterceptor.java index 5abd786dd..db0b07dc7 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceChannelInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceChannelInterceptor.java @@ -23,6 +23,8 @@ import org.springframework.cloud.sleuth.sampler.IsTracingSampler; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; +import java.util.Random; + /** * @author Dave Syer * @@ -31,8 +33,8 @@ public class TraceChannelInterceptor extends AbstractTraceChannelInterceptor { private ThreadLocal traceHolder = new ThreadLocal<>(); - public TraceChannelInterceptor(TraceManager traceManager) { - super(traceManager); + public TraceChannelInterceptor(TraceManager traceManager, Random random) { + super(traceManager, random); } @Override diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceContextPropagationChannelInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceContextPropagationChannelInterceptor.java index d36b02420..e463bd027 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceContextPropagationChannelInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceContextPropagationChannelInterceptor.java @@ -16,9 +16,6 @@ package org.springframework.cloud.sleuth.instrument.integration; -import java.util.HashMap; -import java.util.Map; - import org.springframework.aop.support.AopUtils; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; @@ -31,6 +28,10 @@ import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.support.ChannelInterceptorAdapter; import org.springframework.messaging.support.ExecutorChannelInterceptor; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; /** * The {@link ExecutorChannelInterceptor} implementation responsible for the {@link Span} @@ -92,8 +93,8 @@ public class TraceContextPropagationChannelInterceptor extends ChannelIntercepto return postReceive(message, channel); } - private String getParentId(Span span) { - return span.getParents() != null && !span.getParents().isEmpty() + private Long getParentId(Span span) { + return !span.getParents().isEmpty() ? span.getParents().get(0) : null; } @@ -130,12 +131,12 @@ public class TraceContextPropagationChannelInterceptor extends ChannelIntercepto setHeader(headers, Trace.SPAN_ID_NAME, this.span.getSpanId()); setHeader(headers, Trace.TRACE_ID_NAME, this.span.getTraceId()); setHeader(headers, Trace.SPAN_NAME_NAME, this.span.getName()); - String parentId = getParentId(span); + Long parentId = getParentId(span); if (parentId != null) { setHeader(headers, Trace.PARENT_ID_NAME, parentId); } - String processId = this.span.getProcessId(); - if (processId != null) { + String processId = span.getProcessId(); + if (StringUtils.hasText(processId)) { setHeader(headers, Trace.PROCESS_ID_NAME, processId); } this.messageHeaders = new MessageHeaders(headers); @@ -146,6 +147,9 @@ public class TraceContextPropagationChannelInterceptor extends ChannelIntercepto headers.put(name, value); } } + public void setHeader(Map headers, String name, long value) { + setHeader(headers, name, Span.IdConverter.toHex(value)); + } @Override public Object getPayload() { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceSpringIntegrationAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceSpringIntegrationAutoConfiguration.java index cf70a6c1d..757336fae 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceSpringIntegrationAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceSpringIntegrationAutoConfiguration.java @@ -26,6 +26,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.integration.config.GlobalChannelInterceptor; +import java.util.Random; + /** * @author Spencer Gibb */ @@ -45,13 +47,13 @@ public class TraceSpringIntegrationAutoConfiguration { @Bean @GlobalChannelInterceptor - public TraceChannelInterceptor traceChannelInterceptor(TraceManager traceManager) { - return new TraceChannelInterceptor(traceManager); + public TraceChannelInterceptor traceChannelInterceptor(TraceManager traceManager, Random random) { + return new TraceChannelInterceptor(traceManager, random); } @Bean - public TraceStompMessageChannelInterceptor traceStompMessageChannelInterceptor(TraceManager traceManager) { - return new TraceStompMessageChannelInterceptor(traceManager); + public TraceStompMessageChannelInterceptor traceStompMessageChannelInterceptor(TraceManager traceManager, Random random) { + return new TraceStompMessageChannelInterceptor(traceManager, random); } @Bean diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageChannelInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageChannelInterceptor.java index 52d59c05b..1a59b528a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageChannelInterceptor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageChannelInterceptor.java @@ -22,6 +22,8 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.support.ChannelInterceptor; +import java.util.Random; + /** * Interceptor for Stomp Messages sent over websocket * @@ -32,8 +34,8 @@ import org.springframework.messaging.support.ChannelInterceptor; public class TraceStompMessageChannelInterceptor extends AbstractTraceChannelInterceptor implements ChannelInterceptor { private ThreadLocal traceScopeHolder = new ThreadLocal(); - public TraceStompMessageChannelInterceptor(final TraceManager traceManager) { - super(traceManager); + public TraceStompMessageChannelInterceptor(TraceManager traceManager, Random random) { + super(traceManager, random); } @Override 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 bc9323346..88f8a0cf0 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 @@ -19,6 +19,7 @@ import static org.springframework.util.StringUtils.hasText; import java.io.IOException; import java.util.Enumeration; +import java.util.Random; import java.util.regex.Pattern; import javax.servlet.FilterChain; @@ -40,6 +41,7 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; +import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.util.UrlPathHelper; @@ -68,18 +70,22 @@ public class TraceFilter extends OncePerRequestFilter private final TraceManager traceManager; private final Pattern skipPattern; - private UrlPathHelper urlPathHelper = new UrlPathHelper(); + private final Random random; + private UrlPathHelper urlPathHelper = new UrlPathHelper(); private ApplicationEventPublisher publisher; + public TraceFilter(TraceManager traceManager) { this.traceManager = traceManager; this.skipPattern = DEFAULT_SKIP_PATTERN; + this.random = new Random(); } - public TraceFilter(TraceManager traceManager, Pattern skipPattern) { + public TraceFilter(TraceManager traceManager, Pattern skipPattern, Random random) { this.traceManager = traceManager; this.skipPattern = skipPattern; + this.random = random; } @Override @@ -105,28 +111,28 @@ public class TraceFilter extends OncePerRequestFilter addToResponseIfNotPresent(response, Trace.NOT_SAMPLED_NAME, ""); } - String spanId = getHeader(request, response, Trace.SPAN_ID_NAME); - String traceId = getHeader(request, response, Trace.TRACE_ID_NAME); String name = "http" + uri; - if (hasText(traceId)) { + if (hasHeader(request, response, Trace.TRACE_ID_NAME)) { + long traceId = Span.IdConverter.fromHex(getHeader(request, response, Trace.TRACE_ID_NAME)); + long spanId = hasHeader(request, response, Trace.SPAN_ID_NAME) ? + Span.IdConverter.fromHex(getHeader(request, response, Trace.SPAN_ID_NAME)) : random.nextLong(); MilliSpanBuilder span = MilliSpan.builder().traceId(traceId).spanId(spanId); if (skip) { span.exportable(false); } - String parentId = getHeader(request, response, Trace.PARENT_ID_NAME); String processId = getHeader(request, response, Trace.PROCESS_ID_NAME); String parentName = getHeader(request, response, Trace.SPAN_NAME_NAME); - if (parentName != null) { + if (StringUtils.hasText(parentName)) { span.name(parentName); } else { span.name("parent/" + name); } - if (processId != null) { + if (StringUtils.hasText(processId)) { span.processId(processId); } - if (parentId != null) { - span.parent(parentId); + if (hasHeader(request, response, Trace.PARENT_ID_NAME)) { + span.parent(Span.IdConverter.fromHex(getHeader(request, response, Trace.PARENT_ID_NAME))); } span.remote(true); @@ -181,8 +187,8 @@ public class TraceFilter extends OncePerRequestFilter private void addResponseHeaders(HttpServletResponse response, Span span) { if (span != null) { - response.addHeader(Trace.SPAN_ID_NAME, span.getSpanId()); - response.addHeader(Trace.TRACE_ID_NAME, span.getTraceId()); + response.addHeader(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(span.getSpanId())); + response.addHeader(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(span.getTraceId())); } } @@ -233,6 +239,12 @@ public class TraceFilter extends OncePerRequestFilter } } + private boolean hasHeader(HttpServletRequest request, HttpServletResponse response, + String name) { + String value = request.getHeader(name); + return value != null || response.getHeader(name) != null; + } + private String getHeader(HttpServletRequest request, HttpServletResponse response, String name) { String value = request.getHeader(name); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index 13cbd3b39..f848ee25d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -15,6 +15,7 @@ */ package org.springframework.cloud.sleuth.instrument.web; +import java.util.Random; import java.util.regex.Pattern; import org.springframework.beans.factory.annotation.Autowired; @@ -65,10 +66,10 @@ public class TraceWebAutoConfiguration { } @Bean - public FilterRegistrationBean traceWebFilter(ApplicationEventPublisher publisher) { + public FilterRegistrationBean traceWebFilter(ApplicationEventPublisher publisher, Random random) { Pattern pattern = StringUtils.hasText(this.skipPattern) ? Pattern.compile(this.skipPattern) : TraceFilter.DEFAULT_SKIP_PATTERN; - TraceFilter filter = new TraceFilter(this.traceManager, pattern); + TraceFilter filter = new TraceFilter(this.traceManager, pattern, random); filter.setApplicationEventPublisher(publisher); return new FilterRegistrationBean(filter); } 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 ed15803d1..6c9280e97 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 @@ -16,14 +16,10 @@ package org.springframework.cloud.sleuth.instrument.web.client; -import static java.util.Collections.singletonList; - -import java.io.IOException; -import java.lang.reflect.Type; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - +import com.netflix.hystrix.HystrixCommand; +import feign.*; +import feign.codec.Decoder; +import feign.hystrix.HystrixFeign; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -49,17 +45,15 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Scope; +import org.springframework.util.StringUtils; -import com.netflix.hystrix.HystrixCommand; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; -import feign.Client; -import feign.Feign; -import feign.FeignException; -import feign.RequestInterceptor; -import feign.RequestTemplate; -import feign.Response; -import feign.codec.Decoder; -import feign.hystrix.HystrixFeign; +import static java.util.Collections.singletonList; /** * @@ -125,12 +119,7 @@ public class TraceFeignClientAutoConfiguration { setHeader(template, Trace.NOT_SAMPLED_NAME, ""); return; } - if (span.getSpanId() == null) { - setHeader(template, Trace.TRACE_ID_NAME, span.getTraceId()); - setHeader(template, Trace.NOT_SAMPLED_NAME, ""); - return; - } - template.header(Trace.TRACE_ID_NAME, span.getTraceId()); + template.header(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(span.getTraceId())); setHeader(template, Trace.SPAN_NAME_NAME, span.getName()); setHeader(template, Trace.SPAN_ID_NAME, span.getSpanId()); setHeader(template, Trace.PARENT_ID_NAME, getParentId(span)); @@ -146,8 +135,8 @@ public class TraceFeignClientAutoConfiguration { } } - private String getParentId(Span span) { - return span.getParents() != null && !span.getParents().isEmpty() + private Long getParentId(Span span) { + return !span.getParents().isEmpty() ? span.getParents().get(0) : null; } @@ -158,6 +147,12 @@ public class TraceFeignClientAutoConfiguration { } } + public void setHeader(RequestTemplate request, String name, Long value) { + if (value != null) { + setHeader(request, name, Span.IdConverter.toHex(value)); + } + } + private Map> headersWithTraceId( Map> headers) { Map> newHeaders = new HashMap<>(); @@ -167,11 +162,6 @@ public class TraceFeignClientAutoConfiguration { setHeader(newHeaders, Trace.NOT_SAMPLED_NAME, ""); return newHeaders; } - if (span.getSpanId() == null) { - setHeader(newHeaders, Trace.TRACE_ID_NAME, span.getTraceId()); - setHeader(newHeaders, Trace.NOT_SAMPLED_NAME, ""); - return newHeaders; - } setHeader(newHeaders, Trace.TRACE_ID_NAME, span.getTraceId()); setHeader(newHeaders, Trace.SPAN_ID_NAME, span.getSpanId()); setHeader(newHeaders, Trace.PARENT_ID_NAME, getParentId(span)); @@ -180,10 +170,16 @@ public class TraceFeignClientAutoConfiguration { public void setHeader(Map> headers, String name, String value) { - if (value != null && !headers.containsKey(name) && this.accessor.isTracing()) { + if (StringUtils.hasText(value) && !headers.containsKey(name) && this.accessor.isTracing()) { headers.put(name, singletonList(value)); } } + public void setHeader(Map> headers, String name, + Long value) { + if (value != null ){ + setHeader(headers, name, Span.IdConverter.toHex(value)); + } + } private Span getCurrentSpan() { return this.accessor.getCurrentSpan(); 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 36637a965..e036cd1af 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 @@ -15,8 +15,6 @@ */ package org.springframework.cloud.sleuth.instrument.web.client; -import java.io.IOException; - import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; import org.springframework.cloud.sleuth.TraceAccessor; @@ -29,6 +27,9 @@ 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; + +import java.io.IOException; /** * Interceptor that verifies whether the trance and span id has been set on the request @@ -64,11 +65,6 @@ ApplicationEventPublisherAware { setHeader(request, Trace.NOT_SAMPLED_NAME, ""); return execution.execute(request, body); } - if (span.getSpanId()==null) { - setHeader(request, Trace.TRACE_ID_NAME, span.getTraceId()); - setHeader(request, Trace.NOT_SAMPLED_NAME, ""); - return execution.execute(request, body); - } setHeader(request, Trace.TRACE_ID_NAME, span.getTraceId()); setHeader(request, Trace.SPAN_ID_NAME, span.getSpanId()); setHeader(request, Trace.SPAN_NAME_NAME, span.getName()); @@ -91,17 +87,23 @@ ApplicationEventPublisherAware { } } - private String getParentId(Span span) { - return span.getParents() != null && !span.getParents().isEmpty() ? span + private Long getParentId(Span span) { + return !span.getParents().isEmpty() ? span .getParents().get(0) : null; } 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); } } + public void setHeader(HttpRequest request, String name, Long value) { + if (value != null) { + setHeader(request, name, Span.IdConverter.toHex(value)); + } + } + private Span getCurrentSpan() { return this.accessor.getCurrentSpan(); } 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 da00ad828..b0b3ca4ea 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 @@ -16,8 +16,8 @@ package org.springframework.cloud.sleuth.instrument.zuul; -import java.util.Map; - +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; import org.springframework.cloud.sleuth.TraceAccessor; @@ -27,8 +27,7 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.util.ReflectionUtils; -import com.netflix.zuul.ZuulFilter; -import com.netflix.zuul.context.RequestContext; +import java.util.Map; /** * @author Dave Syer @@ -65,11 +64,6 @@ ApplicationEventPublisherAware { setHeader(response, Trace.NOT_SAMPLED_NAME, ""); return null; } - if (span.getSpanId()==null) { - setHeader(response, Trace.TRACE_ID_NAME, span.getTraceId()); - setHeader(response, Trace.NOT_SAMPLED_NAME, ""); - return null; - } try { setHeader(response, Trace.SPAN_ID_NAME, span.getSpanId()); setHeader(response, Trace.TRACE_ID_NAME, span.getTraceId()); @@ -89,8 +83,8 @@ ApplicationEventPublisherAware { return this.accessor.getCurrentSpan(); } - private String getParentId(Span span) { - return span.getParents() != null && !span.getParents().isEmpty() ? span + private Long getParentId(Span span) { + return !span.getParents().isEmpty() ? span .getParents().get(0) : null; } @@ -99,6 +93,9 @@ ApplicationEventPublisherAware { request.put(name, value); } } + public void setHeader(Map request, String name, Long value) { + setHeader(request, name, Span.IdConverter.toHex(value)); + } @Override public String filterType() { 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 8bad6052f..c08f0bfb1 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 @@ -16,9 +16,9 @@ package org.springframework.cloud.sleuth.instrument.zuul; -import java.io.InputStream; -import java.net.URISyntaxException; - +import com.netflix.client.http.HttpRequest; +import com.netflix.niws.client.http.RestClient; +import lombok.SneakyThrows; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommand; import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonCommandFactory; @@ -32,10 +32,8 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.util.MultiValueMap; -import com.netflix.client.http.HttpRequest; -import com.netflix.niws.client.http.RestClient; - -import lombok.SneakyThrows; +import java.io.InputStream; +import java.net.URISyntaxException; /** * @author Spencer Gibb @@ -96,12 +94,6 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand setHeader(requestBuilder, Trace.NOT_SAMPLED_NAME, ""); return; } - if (span.getSpanId()==null) { - setHeader(requestBuilder, Trace.TRACE_ID_NAME, span.getTraceId()); - setHeader(requestBuilder, Trace.NOT_SAMPLED_NAME, ""); - return; - } - setHeader(requestBuilder, Trace.TRACE_ID_NAME, span.getTraceId()); setHeader(requestBuilder, Trace.SPAN_ID_NAME, span.getSpanId()); setHeader(requestBuilder, Trace.SPAN_NAME_NAME, span.getName()); @@ -118,8 +110,8 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand } } - private String getParentId(Span span) { - return span.getParents() != null && !span.getParents().isEmpty() + private Long getParentId(Span span) { + return !span.getParents().isEmpty() ? span.getParents().get(0) : null; } @@ -129,6 +121,10 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand } } + public void setHeader(HttpRequest.Builder builder, String name, Long value) { + setHeader(builder, name, Span.IdConverter.toHex(value)); + } + private Span getCurrentSpan() { return this.accessor.getCurrentSpan(); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanListener.java index c16c8a81a..3cc9b4dbe 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanListener.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanListener.java @@ -38,9 +38,9 @@ public class Slf4jSpanListener { @Order(Ordered.LOWEST_PRECEDENCE) public void start(SpanAcquiredEvent event) { Span span = event.getSpan(); - MDC.put(Trace.SPAN_ID_NAME, span.getSpanId()); + MDC.put(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(span.getSpanId())); MDC.put(Trace.SPAN_EXPORT_NAME, String.valueOf(span.isExportable())); - MDC.put(Trace.TRACE_ID_NAME, span.getTraceId()); + MDC.put(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(span.getTraceId())); log.trace("Starting span: {}", span); if (event.getParent() != null) { log.trace("With parent: {}", event.getParent()); @@ -51,8 +51,8 @@ public class Slf4jSpanListener { @Order(Ordered.LOWEST_PRECEDENCE) public void continued(SpanContinuedEvent event) { Span span = event.getSpan(); - MDC.put(Trace.SPAN_ID_NAME, span.getSpanId()); - MDC.put(Trace.TRACE_ID_NAME, span.getTraceId()); + MDC.put(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(span.getSpanId())); + MDC.put(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(span.getTraceId())); MDC.put(Trace.SPAN_EXPORT_NAME, String.valueOf(span.isExportable())); log.trace("Continued span: {}", event.getSpan()); } @@ -63,7 +63,7 @@ public class Slf4jSpanListener { log.trace("Stopped span: {}", event.getSpan()); if (event.getParent() != null) { log.trace("With parent: {}", event.getParent()); - MDC.put(Trace.SPAN_ID_NAME, event.getParent().getSpanId()); + MDC.put(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(event.getParent().getSpanId())); MDC.put(Trace.SPAN_EXPORT_NAME, String.valueOf(event.getParent().isExportable())); } else { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/DefaultStringToUuidConverter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/DefaultStringToUuidConverter.java deleted file mode 100644 index 7652b6af9..000000000 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/DefaultStringToUuidConverter.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.springframework.cloud.sleuth.sampler; - -import lombok.extern.slf4j.Slf4j; - -import java.util.UUID; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Default implementation that converts String into UUID - * On parse exceptions a null is returned. - * - * @author Marcin Grzejszczak - * @author Adrian Cole - */ -@Slf4j -public class DefaultStringToUuidConverter implements StringToUuidConverter { - - /** Returns a UUID parsed from the input, or null if failed for any reason. */ - @Override - public UUID convert(String source) { - try { - UUID uuid = UUID.fromString(source); - incrementSuccess(); - return uuid; - } catch (IllegalArgumentException e) { - log.debug("Exception occurred while trying to parse String to UUID", e); - incrementFailures(); - return null; - } - } - - /** - * Override to increment your counter. - */ - protected void incrementSuccess() { - } - - - /** - * Override to increment your counter. - */ - protected void incrementFailures() { - } -} diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/PercentageBasedSampler.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/PercentageBasedSampler.java index be17155b7..60de8b7d7 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/PercentageBasedSampler.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/PercentageBasedSampler.java @@ -26,22 +26,22 @@ public class PercentageBasedSampler implements Sampler { private final SamplerConfiguration configuration; private final TraceAccessor traceAccessor; - private final StringToUuidConverter converter; - public PercentageBasedSampler(SamplerConfiguration configuration, TraceAccessor traceAccessor, StringToUuidConverter converter) { + public PercentageBasedSampler(SamplerConfiguration configuration, TraceAccessor traceAccessor) { this.configuration = configuration; this.traceAccessor = traceAccessor; - this.converter = converter; } @Override public boolean next(Void info) { Span currentSpan = traceAccessor.getCurrentSpan(); - if (currentSpan == null) { + long threshold = Math.abs(Long.MAX_VALUE * (int) (configuration.getPercentage() * 100)); // drops fractional percentage. + if (currentSpan == null || threshold == 0L) { return false; } - return new UuidTraceIdToThresholdComparable(configuration.getPercentage(), converter) - .compareTo(currentSpan.getTraceId()) <= 0; + long traceId = currentSpan.getTraceId(); + Long mod = Math.abs(traceId % 100); + return mod.compareTo(threshold) <= 0; } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/UuidTraceIdToThresholdComparable.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/UuidTraceIdToThresholdComparable.java deleted file mode 100644 index 2fa5a6d2a..000000000 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/UuidTraceIdToThresholdComparable.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.springframework.cloud.sleuth.sampler; - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.UUID; - -/** - * Given the absolute value of a random 128 bit trace id, we expect inputs to be balanced across - * 0-MAX. Threshold is the range of inputs between 0-MAX that we retain. - * - * This decodes a trace id in UUID format into a 128 bit number, then compares it against a threshold. - * - * @author Marcin Grzejszczak - * @author Adrian Cole - */ -final class UuidTraceIdToThresholdComparable implements Comparable { - - private static final int SIXTY_FOUR_BITS = 64; - private static final int GREATER_THAN_THRESHOLD = 1; - - /** - * 0111....1111 ('0' - for the sign and then 127 times '1') - */ - static final BigInteger MAX_128 = max_128signed(); - - private final BigInteger threshold; - - private final StringToUuidConverter stringToUuidConverter; - UuidTraceIdToThresholdComparable(float rate, StringToUuidConverter converter) { - threshold = MAX_128 - .multiply(BigInteger.valueOf((int) (rate * 100))) // drops fractional percentage. - .divide(BigInteger.valueOf(100)); - stringToUuidConverter = converter; - } - - UuidTraceIdToThresholdComparable(float rate) { - this(rate, new DefaultStringToUuidConverter()); - } - - /** - * Compares the given Trace Id to the provided threshold - * @param traceId - the UUID version of Trace Id - */ - @Override - public int compareTo(String traceId) { - UUID uuid = stringToUuidConverter.convert(traceId); - if (uuid == null) { - return GREATER_THAN_THRESHOLD; - } - BigInteger asInteger = BigInteger.valueOf(uuid.getMostSignificantBits()) - .shiftLeft(SIXTY_FOUR_BITS) - .add(BigInteger.valueOf(uuid.getLeastSignificantBits())) - .abs(); - return asInteger.compareTo(threshold); - } - - /** - * The Long.MAX_VALUE in binary 0 followed by 63 1s. - * - * We simulate a 128bit long, by doing the same, except following by 127 1s - */ - static BigInteger max_128signed() { - byte[] max_128signed = new byte[16]; - Arrays.fill(max_128signed, (byte) -1); // initialize to 11111111 - max_128signed[0] = (byte) 127; // reset MSBs to 01111111 - return new BigInteger(max_128signed); - } -} \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTraceManager.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTraceManager.java index 5acff4222..f136b375d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTraceManager.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/trace/DefaultTraceManager.java @@ -18,6 +18,7 @@ package org.springframework.cloud.sleuth.trace; import static org.springframework.cloud.sleuth.util.ExceptionUtils.warn; +import java.util.Random; import java.util.concurrent.Callable; import org.springframework.cloud.sleuth.MilliSpan; @@ -32,7 +33,6 @@ import org.springframework.cloud.sleuth.instrument.TraceCallable; import org.springframework.cloud.sleuth.instrument.TraceRunnable; import org.springframework.cloud.sleuth.util.ExceptionUtils; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.util.IdGenerator; /** * @author Spencer Gibb @@ -41,14 +41,14 @@ public class DefaultTraceManager implements TraceManager { private final Sampler defaultSampler; - private final IdGenerator idGenerator; - private final ApplicationEventPublisher publisher; - public DefaultTraceManager(Sampler defaultSampler, IdGenerator idGenerator, - ApplicationEventPublisher publisher) { + private final Random random; + + public DefaultTraceManager(Sampler defaultSampler, + Random random, ApplicationEventPublisher publisher) { this.defaultSampler = defaultSampler; - this.idGenerator = idGenerator; + this.random = random; this.publisher = publisher; } @@ -79,7 +79,7 @@ public class DefaultTraceManager implements TraceManager { } else { // Non-exportable so we keep the trace but not other data - String id = createId(); + long id = createId(); span = MilliSpan.builder().begin(System.currentTimeMillis()).name(name) .traceId(id).spanId(id).exportable(false).build(); this.publisher.publishEvent(new SpanAcquiredEvent(this, span)); @@ -149,7 +149,7 @@ public class DefaultTraceManager implements TraceManager { } protected Span createChild(Span parent, String name) { - String id = createId(); + long id = createId(); if (parent == null) { MilliSpan span = MilliSpan.builder().begin(System.currentTimeMillis()) .name(name).traceId(id).spanId(id).build(); @@ -169,8 +169,8 @@ public class DefaultTraceManager implements TraceManager { } } - private String createId() { - return this.idGenerator.generateId().toString(); + private long createId() { + return random.nextLong(); } @Override diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceManagerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceManagerTests.java index 1e20fb5fb..3eb453aff 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceManagerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/DefaultTraceManagerTests.java @@ -28,15 +28,18 @@ import org.springframework.cloud.sleuth.trace.DefaultTraceManager; import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.util.JdkIdGenerator; import java.util.ArrayList; import java.util.List; +import java.util.Random; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.*; +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 @@ -62,8 +65,7 @@ public class DefaultTraceManagerTests { public void tracingWorks() { ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class); - DefaultTraceManager traceManager = new DefaultTraceManager(new IsTracingSampler(), - new JdkIdGenerator(), publisher); + DefaultTraceManager traceManager = new DefaultTraceManager(new IsTracingSampler(), new Random(), publisher); Trace trace = traceManager.startSpan(CREATE_SIMPLE_TRACE, new AlwaysSampler(), null); try { @@ -97,7 +99,7 @@ public class DefaultTraceManagerTests { assertThat("gen4 was non-empty", gen4.isEmpty(), is(true)); } - private Span assertSpan(List spans, String parentId, String name) { + private Span assertSpan(List spans, Long parentId, String name) { List found = findSpans(spans, parentId); assertThat("more than one span with parentId " + parentId, found.size(), is(1)); Span span = found.get(0); @@ -106,7 +108,7 @@ public class DefaultTraceManagerTests { return span; } - private List findSpans(List spans, String parentId) { + private List findSpans(List spans, Long parentId) { List found = new ArrayList<>(); for (Span span : spans) { if (parentId == null && span.getParents().isEmpty()) { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/MilliSpanTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/MilliSpanTests.java index d50c6ab70..e9a348bef 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/MilliSpanTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/MilliSpanTests.java @@ -16,10 +16,10 @@ package org.springframework.cloud.sleuth; -import java.util.Collections; - import org.junit.Test; +import java.util.Collections; + /** * @author Rob Winch * @author Spencer Gibb @@ -28,7 +28,7 @@ public class MilliSpanTests { @Test(expected = UnsupportedOperationException.class) public void getAnnotationsReadOnly() { - MilliSpan span = new MilliSpan(1, 2, "name", "traceId", Collections.emptyList(), "spanId", true, true, "processId"); + MilliSpan span = new MilliSpan(1, 2, "name", 1L, Collections.emptyList(), 2L, true, true, "process"); span.tags().put("a", "b"); } @@ -36,7 +36,7 @@ public class MilliSpanTests { @Test(expected = UnsupportedOperationException.class) public void getTimelineAnnotationsReadOnly() { - MilliSpan span = new MilliSpan(1, 2, "name", "traceId", Collections.emptyList(), "spanId", true, true, "processId"); + MilliSpan span = new MilliSpan(1, 2, "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/SpanTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java new file mode 100644 index 000000000..1f4e341fc --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java @@ -0,0 +1,34 @@ +package org.springframework.cloud.sleuth; + +import org.junit.Test; + +import static org.assertj.core.api.BDDAssertions.then; + +/** + * @author Marcin Grzejszczak + */ +public class SpanTest { + + @Test + public void should_convert_long_to_hex_string() throws Exception { + long someLong = 123123L; + + String hexString = Span.IdConverter.toHex(someLong); + + then(hexString).isEqualTo("1e0f3"); + } + + @Test + public void should_convert_hex_string_to_long() throws Exception { + String hexString = "1e0f3"; + + long someLong = Span.IdConverter.fromHex(hexString); + + then(someLong).isEqualTo(123123L); + } + + @Test(expected = IllegalArgumentException.class) + public void should_throw_exception_when_null_string_is_to_be_converted_to_long() throws Exception { + Span.IdConverter.fromHex(null); + } +} \ No newline at end of file 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 296340dde..add1bdb64 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 @@ -1,33 +1,39 @@ package org.springframework.cloud.sleuth.assertions; -import java.util.Objects; - +import lombok.extern.slf4j.Slf4j; import org.assertj.core.api.AbstractAssert; import org.springframework.cloud.sleuth.Span; +import java.util.Objects; + +@Slf4j public class SpanAssert extends AbstractAssert { - public SpanAssert(Span actual) { - super(actual, SpanAssert.class); - } + public SpanAssert(Span actual) { + super(actual, SpanAssert.class); + } - public static SpanAssert then(Span actual) { - return new SpanAssert(actual); - } + public static SpanAssert then(Span actual) { + return new SpanAssert(actual); + } - public SpanAssert hasTraceIdEqualTo(String traceId) { - isNotNull(); - if (!Objects.equals(actual.getTraceId(), traceId)) { - failWithMessage("Expected span's traceId to be <%s> but was <%s>", traceId, actual.getTraceId()); - } - return this; - } + public SpanAssert hasTraceIdEqualTo(long traceId) { + isNotNull(); + if (!Objects.equals(actual.getTraceId(), traceId)) { + String message = String.format("Expected span's traceId to be <%s> but was <%s>", traceId, actual.getTraceId()); + log.error(message); + failWithMessage(message); + } + return this; + } - public SpanAssert hasNameNotEqualTo(String name) { - isNotNull(); - if (Objects.equals(actual.getName(), name)) { - failWithMessage("Expected span's name not to be <%s> but was <%s>", name, actual.getName()); - } - return this; - } + public SpanAssert hasNameNotEqualTo(String name) { + isNotNull(); + if (Objects.equals(actual.getName(), name)) { + String message = String.format("Expected span's name not to be <%s> but was <%s>", name, actual.getName()); + 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/TraceCallableTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceCallableTests.java index 2fe938000..c167922f3 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceCallableTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceCallableTests.java @@ -1,11 +1,5 @@ package org.springframework.cloud.sleuth.instrument; -import static org.assertj.core.api.BDDAssertions.then; - -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; @@ -17,14 +11,20 @@ import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.trace.DefaultTraceManager; import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.util.JdkIdGenerator; + +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) public class TraceCallableTests { ExecutorService executor = Executors.newSingleThreadExecutor(); TraceManager traceManager = new DefaultTraceManager(new AlwaysSampler(), - new JdkIdGenerator(), Mockito.mock(ApplicationEventPublisher.class)); + new Random(), Mockito.mock(ApplicationEventPublisher.class)); @After public void clean() { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceRunnableTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceRunnableTests.java index 8ad69a3f7..85712ccdf 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceRunnableTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/TraceRunnableTests.java @@ -1,10 +1,5 @@ package org.springframework.cloud.sleuth.instrument; -import static org.assertj.core.api.BDDAssertions.then; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -16,14 +11,19 @@ import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.trace.DefaultTraceManager; import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.util.JdkIdGenerator; + +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static org.assertj.core.api.BDDAssertions.then; @RunWith(MockitoJUnitRunner.class) public class TraceRunnableTests { ExecutorService executor = Executors.newSingleThreadExecutor(); TraceManager traceManager = new DefaultTraceManager(new AlwaysSampler(), - new JdkIdGenerator(), Mockito.mock(ApplicationEventPublisher.class)); + new Random(), Mockito.mock(ApplicationEventPublisher.class)); @After public void cleanup() { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/executor/TraceableExecutorServiceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/executor/TraceableExecutorServiceTests.java index afb25cc32..c137165c8 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/executor/TraceableExecutorServiceTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/executor/TraceableExecutorServiceTests.java @@ -14,11 +14,11 @@ import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.trace.DefaultTraceManager; import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.util.JdkIdGenerator; import java.util.ArrayList; import java.util.List; import java.util.Queue; +import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutorService; @@ -39,8 +39,7 @@ public class TraceableExecutorServiceTests { @Before public void setup() { - //traceManager = new DefaultTraceManager(new AlwaysSampler(), new RandomLongSpanIdGenerator(), publisher); - traceManager = new DefaultTraceManager(new AlwaysSampler(), new JdkIdGenerator(), publisher); + traceManager = new DefaultTraceManager(new AlwaysSampler(), new Random(), publisher); traceManagerableExecutorService = new TraceableExecutorService(executorService, traceManager); TraceContextHolder.removeCurrentTrace(); } @@ -74,8 +73,8 @@ public class TraceableExecutorServiceTests { class SpanVerifyingRunnable implements Runnable { - Queue traceIds = new ConcurrentLinkedQueue<>(); - Queue spanIds = new ConcurrentLinkedQueue<>(); + Queue traceIds = new ConcurrentLinkedQueue<>(); + Queue spanIds = new ConcurrentLinkedQueue<>(); @Override public void run() { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SpanPassingForHystrixViaAnnotationsIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SpanPassingForHystrixViaAnnotationsIntegrationTests.java index a71c8a4a6..624b7f4ea 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SpanPassingForHystrixViaAnnotationsIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SpanPassingForHystrixViaAnnotationsIntegrationTests.java @@ -83,11 +83,9 @@ public class SpanPassingForHystrixViaAnnotationsIntegrationTests { spanCaughtFromHystrixThread = new AtomicReference<>(TraceContextHolder.getCurrentSpan()); } - public String getTraceId() { + public Long getTraceId() { if (spanCaughtFromHystrixThread == null || - spanCaughtFromHystrixThread.get() == null || - (spanCaughtFromHystrixThread.get() != null && - spanCaughtFromHystrixThread.get().getTraceId() == null)) { + spanCaughtFromHystrixThread.get() == null) { return null; } return spanCaughtFromHystrixThread.get().getTraceId(); 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 1c254537b..ea923d8b1 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,7 @@ 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 com.netflix.hystrix.HystrixCommandKey; +import com.netflix.hystrix.HystrixThreadPoolProperties; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -15,16 +13,18 @@ import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.trace.DefaultTraceManager; import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.util.JdkIdGenerator; -import com.netflix.hystrix.HystrixCommandKey; -import com.netflix.hystrix.HystrixThreadPoolProperties; +import java.util.Random; + +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 String EXPECTED_TRACE_ID = "A"; + static final long EXPECTED_TRACE_ID = 1L; TraceManager traceManager = new DefaultTraceManager(new AlwaysSampler(), - new JdkIdGenerator(), Mockito.mock(ApplicationEventPublisher.class)); + new Random(), Mockito.mock(ApplicationEventPublisher.class)); @Before public void setup() { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/AbstractTraceStompIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/AbstractTraceStompIntegrationTests.java index f4518936a..c4aa97a66 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/AbstractTraceStompIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/AbstractTraceStompIntegrationTests.java @@ -50,19 +50,19 @@ abstract class AbstractTraceStompIntegrationTests { then(stompMessageHandler.message).isNotNull(); } - String thenSpanIdFromHeadersIsNotEmpty() { - String header = getValueFromHeaders(Trace.SPAN_ID_NAME); - then(header).as("Span id should not be empty").isNotEmpty(); + Long thenSpanIdFromHeadersIsNotEmpty() { + Long header = getValueFromHeaders(Trace.SPAN_ID_NAME, Long.class); + then(header).as("Span id should not be empty").isNotNull(); return header; } - String thenTraceIdFromHeadersIsNotEmpty() { - String header = getValueFromHeaders(Trace.TRACE_ID_NAME); - then(header).as("Trace id should not be empty").isNotEmpty(); + Long thenTraceIdFromHeadersIsNotEmpty() { + Long header = getValueFromHeaders(Trace.TRACE_ID_NAME, Long.class); + then(header).as("Trace id should not be empty").isNotNull(); return header; } - String getValueFromHeaders(String headerName) { - return stompMessageHandler.message.getHeaders().get(headerName, String.class); + T getValueFromHeaders(String headerName, Class type) { + return stompMessageHandler.message.getHeaders().get(headerName, type); } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceChannelInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceChannelInterceptorTests.java index 4b810b38c..95f71a909 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceChannelInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceChannelInterceptorTests.java @@ -16,14 +16,6 @@ package org.springframework.cloud.sleuth.instrument.integration; -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; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -52,6 +44,12 @@ import org.springframework.messaging.MessagingException; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.BDDAssertions.then; +import static org.junit.Assert.*; + /** * @author Dave Syer */ @@ -109,14 +107,16 @@ public class TraceChannelInterceptorTests implements MessageHandler { @Test public void parentSpanIncluded() { - this.channel.send(MessageBuilder.withPayload("hi").setHeader(Trace.TRACE_ID_NAME, "parent") + this.channel.send(MessageBuilder.withPayload("hi").setHeader(Trace.TRACE_ID_NAME, 10L) + .setHeader(Trace.SPAN_ID_NAME, 20L) .build()); assertNotNull("message was null", this.message); String spanId = this.message.getHeaders().get(Trace.SPAN_ID_NAME, String.class); assertNotNull("spanId was null", spanId); - String traceId = this.message.getHeaders().get(Trace.TRACE_ID_NAME, String.class); - assertEquals("parent", traceId); + long traceId = Span.IdConverter.fromHex(this.message.getHeaders().get(Trace.TRACE_ID_NAME, String.class)); + then(traceId).isEqualTo(10L); + then(spanId).isNotEqualTo(20L); assertNull(TraceContextHolder.getCurrentTrace()); assertEquals(1, this.app.events.size()); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceContextPropagationChannelInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceContextPropagationChannelInterceptorTests.java index fad7f88ba..faac69633 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceContextPropagationChannelInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceContextPropagationChannelInterceptorTests.java @@ -16,9 +16,6 @@ package org.springframework.cloud.sleuth.instrument.integration; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -27,6 +24,7 @@ import org.springframework.beans.factory.annotation.Qualifier; 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.Trace; import org.springframework.cloud.sleuth.TraceManager; import org.springframework.cloud.sleuth.instrument.integration.TraceContextPropagationChannelInterceptorTests.App; @@ -41,6 +39,9 @@ import org.springframework.messaging.PollableChannel; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + /** * @author Spencer Gibb */ @@ -67,17 +68,17 @@ public class TraceContextPropagationChannelInterceptorTests { Trace trace = this.traceManager.startSpan("testSendMessage", new AlwaysSampler(), null); this.channel.send(MessageBuilder.withPayload("hi").build()); - String expectedSpanId = trace.getSpan().getSpanId(); + Long expectedSpanId = trace.getSpan().getSpanId(); this.traceManager.close(trace); Message message = this.channel.receive(0); assertNotNull("message was null", message); - String spanId = message.getHeaders().get(Trace.SPAN_ID_NAME, String.class); + Long spanId = Span.IdConverter.fromHex(message.getHeaders().get(Trace.SPAN_ID_NAME, String.class)); assertEquals("spanId was wrong", expectedSpanId, spanId); - String traceId = message.getHeaders().get(Trace.TRACE_ID_NAME, String.class); + long traceId = Span.IdConverter.fromHex(message.getHeaders().get(Trace.TRACE_ID_NAME, String.class)); assertNotNull("traceId was null", traceId); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageChannelInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageChannelInterceptorTests.java index c2ff56a61..6bc96a092 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageChannelInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageChannelInterceptorTests.java @@ -55,8 +55,8 @@ public class TraceStompMessageChannelInterceptorTests extends AbstractTraceStomp whenTheMessageWasSent(message); this.traceManager.close(trace); - String spanId = thenSpanIdFromHeadersIsNotEmpty(); - String traceId = thenTraceIdFromHeadersIsNotEmpty(); + Long spanId = thenSpanIdFromHeadersIsNotEmpty(); + long traceId = thenTraceIdFromHeadersIsNotEmpty(); then(traceId).isEqualTo(trace.getSpan().getTraceId()); then(spanId).isEqualTo(trace.getSpan().getSpanId()); then(TraceContextHolder.getCurrentTrace()).isNull(); @@ -67,7 +67,7 @@ public class TraceStompMessageChannelInterceptorTests extends AbstractTraceStomp } private String thenSpanIdFromHeadersIsEmpty() { - String header = getValueFromHeaders(Trace.SPAN_ID_NAME); + String header = getValueFromHeaders(Trace.SPAN_ID_NAME, String.class); then(header).as("Span id should be empty").isNullOrEmpty(); return header; } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageContextPropagationChannelInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageContextPropagationChannelInterceptorTests.java index abf42361d..ecf10a6ea 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageContextPropagationChannelInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/integration/TraceStompMessageContextPropagationChannelInterceptorTests.java @@ -32,11 +32,11 @@ public class TraceStompMessageContextPropagationChannelInterceptorTests extends Message m = givenMessageToBeSampled(); whenTheMessageWasSent(m); - String expectedTraceId = trace.getSpan().getTraceId(); + Long expectedTraceId = trace.getSpan().getTraceId(); this.traceManager.close(trace); thenReceivedMessageIsNotNull(); - String traceId = thenTraceIdFromHeadersIsNotEmpty(); + long traceId = thenTraceIdFromHeadersIsNotEmpty(); then(traceId).isEqualTo(expectedTraceId); thenSpanIdFromHeadersIsNotEmpty(); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/RestTemplateTraceAspectIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/RestTemplateTraceAspectIntegrationTests.java index 120a218ff..40198c4be 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/RestTemplateTraceAspectIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/RestTemplateTraceAspectIntegrationTests.java @@ -122,7 +122,7 @@ public class RestTemplateTraceAspectIntegrationTests extends AbstractMvcWiremock }; private String callWiremockAndReturnOk() { - this.restTemplate.getForObject("http://localhost:"+this.httpMockServer.port(), String.class); + this.restTemplate.getForObject("http://localhost:" + this.httpMockServer.port(), String.class); return "OK"; } } 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 8111f6f33..e7e5a53ae 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,10 +1,7 @@ package org.springframework.cloud.sleuth.instrument.web; -import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then; - -import java.util.concurrent.atomic.AtomicReference; - +import com.jayway.awaitility.Awaitility; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -20,7 +17,9 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import com.jayway.awaitility.Awaitility; +import java.util.concurrent.atomic.AtomicReference; + +import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { @@ -79,24 +78,22 @@ public class TraceAsyncIntegrationTests { static class ClassPerformingAsyncLogic { - AtomicReference span; + AtomicReference span = new AtomicReference<>(); @Async public void invokeAsynchronousLogic() { - span = new AtomicReference<>(TraceContextHolder.getCurrentSpan()); + span.set(TraceContextHolder.getCurrentSpan()); } - public String getTraceId() { - if (span == null || (span.get() != null - && span.get().getTraceId() == null)) { + public Long getTraceId() { + if (span.get() == null) { return null; } return span.get().getTraceId(); } public String getSpanName() { - if (span == null - || (span.get() != null && span.get().getName() == null)) { + if (span.get() != null && span.get().getName() == null) { return null; } return span.get().getName(); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegartionTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegartionTests.java deleted file mode 100644 index 5c94e700d..000000000 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegartionTests.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.springframework.cloud.sleuth.instrument.web; - -import static org.assertj.core.api.BDDAssertions.then; - -import java.util.UUID; - -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.Trace; -import org.springframework.cloud.sleuth.TraceManager; -import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration; -import org.springframework.cloud.sleuth.instrument.web.common.AbstractMvcIntegrationTest; -import org.springframework.http.MediaType; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; - -@RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(TraceFilterIntegartionTests.class) -@DefaultTestAutoConfiguration -public class TraceFilterIntegartionTests extends AbstractMvcIntegrationTest { - - @Autowired - TraceManager traceManager; - - @Test - public void should_create_and_return_trace_in_HTTP_header() throws Exception { - MvcResult mvcResult = whenSentPingWithoutTracingData(); - - then(tracingHeaderFrom(mvcResult)).isNotNull().isNotEmpty(); - } - - @Test - public void when_correlationId_is_sent_should_not_create_a_new_one_but_return_the_existing_one_instead() - throws Exception { - String expectedTraceId = "passedCorId"; - - MvcResult mvcResult = whenSentPingWithTraceId(expectedTraceId); - - then(tracingHeaderFrom(mvcResult)).isEqualTo(expectedTraceId); - } - - @Override - protected void configureMockMvcBuilder(DefaultMockMvcBuilder mockMvcBuilder) { - mockMvcBuilder.addFilters(new TraceFilter(this.traceManager)); - } - - private MvcResult whenSentPingWithoutTracingData() throws Exception { - return this.mockMvc - .perform(MockMvcRequestBuilders.get("/ping").accept(MediaType.TEXT_PLAIN)) - .andReturn(); - } - - private MvcResult whenSentPingWithTraceId(String passedCorrelationId) - throws Exception { - return sendPingWithTraceId(Trace.TRACE_ID_NAME, passedCorrelationId); - } - - private MvcResult sendPingWithTraceId(String headerName, String passedCorrelationId) - throws Exception { - return this.mockMvc - .perform(MockMvcRequestBuilders.get("/ping").accept(MediaType.TEXT_PLAIN) - .header(headerName, passedCorrelationId) - .header(Trace.SPAN_ID_NAME, UUID.randomUUID().toString())) - .andReturn(); - } - - private String tracingHeaderFrom(MvcResult mvcResult) { - return mvcResult.getResponse().getHeader(Trace.TRACE_ID_NAME); - } -} diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegrationTests.java index 793228cf1..9c93c823c 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegrationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterIntegrationTests.java @@ -1,87 +1,75 @@ -/* - * Copyright 2013-2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package org.springframework.cloud.sleuth.instrument.web; -import static org.junit.Assert.assertNull; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; - -import org.junit.Before; 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.Trace; import org.springframework.cloud.sleuth.TraceManager; -import org.springframework.cloud.sleuth.sampler.AlwaysSampler; -import org.springframework.cloud.sleuth.trace.DefaultTraceManager; -import org.springframework.cloud.sleuth.trace.TraceContextHolder; -import org.springframework.context.support.StaticApplicationContext; +import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration; +import org.springframework.cloud.sleuth.instrument.web.common.AbstractMvcIntegrationTest; import org.springframework.http.MediaType; -import org.springframework.mock.web.MockFilterChain; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.mock.web.MockServletContext; -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.util.JdkIdGenerator; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; -import lombok.SneakyThrows; +import java.util.Random; -/** - * @author Spencer Gibb - * @author Dave Syer - */ -public class TraceFilterIntegrationTests { +import static org.assertj.core.api.BDDAssertions.then; - private StaticApplicationContext context = new StaticApplicationContext(); +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(TraceFilterIntegrationTests.class) +@DefaultTestAutoConfiguration +public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest { - private TraceManager traceManager = new DefaultTraceManager(new AlwaysSampler(), - new JdkIdGenerator(), this.context); + @Autowired + TraceManager traceManager; - private MockHttpServletRequest request; - private MockHttpServletResponse response; - private MockFilterChain filterChain; + @Test + public void should_create_and_return_trace_in_HTTP_header() throws Exception { + MvcResult mvcResult = whenSentPingWithoutTracingData(); - @Before - @SneakyThrows - public void init() { - TraceContextHolder.removeCurrentTrace(); - this.context.refresh(); - this.request = builder().buildRequest(new MockServletContext()); - this.response = new MockHttpServletResponse(); - this.response.setContentType(MediaType.APPLICATION_JSON_VALUE); - this.filterChain = new MockFilterChain(); - } - - public MockHttpServletRequestBuilder builder() { - return get("/").accept(MediaType.APPLICATION_JSON) - .header("User-Agent", "MockMvc"); + then(tracingHeaderFrom(mvcResult)).isNotNull(); } @Test - public void startsNewTrace() throws Exception { - TraceFilter filter = new TraceFilter(this.traceManager); - filter.doFilter(this.request, this.response, this.filterChain); - assertNull(TraceContextHolder.getCurrentTrace()); + public void when_correlationId_is_sent_should_not_create_a_new_one_but_return_the_existing_one_instead() + throws Exception { + Long expectedTraceId = new Random().nextLong(); + + MvcResult mvcResult = whenSentPingWithTraceId(expectedTraceId); + + then(tracingHeaderFrom(mvcResult)).isEqualTo(expectedTraceId); } - @Test - public void continuesSpanFromHeaders() throws Exception { - this.request = builder().header(Trace.SPAN_ID_NAME, "myspan") - .header(Trace.TRACE_ID_NAME, "mytraceManager").buildRequest(new MockServletContext()); - TraceFilter filter = new TraceFilter(this.traceManager); - filter.doFilter(this.request, this.response, this.filterChain); - assertNull(TraceContextHolder.getCurrentSpan()); + @Override + protected void configureMockMvcBuilder(DefaultMockMvcBuilder mockMvcBuilder) { + mockMvcBuilder.addFilters(new TraceFilter(this.traceManager)); } + private MvcResult whenSentPingWithoutTracingData() throws Exception { + return this.mockMvc + .perform(MockMvcRequestBuilders.get("/ping").accept(MediaType.TEXT_PLAIN)) + .andReturn(); + } + + private MvcResult whenSentPingWithTraceId(Long passedTraceId) + throws Exception { + return sendPingWithTraceId(Trace.TRACE_ID_NAME, passedTraceId); + } + + private MvcResult sendPingWithTraceId(String headerName, Long passedCorrelationId) + throws Exception { + return this.mockMvc + .perform(MockMvcRequestBuilders.get("/ping").accept(MediaType.TEXT_PLAIN) + .header(headerName, Span.IdConverter.toHex(passedCorrelationId)) + .header(Trace.SPAN_ID_NAME, Span.IdConverter.toHex(new Random().nextLong()))) + .andReturn(); + } + + private Long tracingHeaderFrom(MvcResult mvcResult) { + return Span.IdConverter.fromHex(mvcResult.getResponse().getHeader(Trace.TRACE_ID_NAME)); + } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterMockChainIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterMockChainIntegrationTests.java new file mode 100644 index 000000000..32fa03a75 --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterMockChainIntegrationTests.java @@ -0,0 +1,88 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.sleuth.instrument.web; + +import lombok.SneakyThrows; +import org.junit.Before; +import org.junit.Test; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.TraceManager; +import org.springframework.cloud.sleuth.sampler.AlwaysSampler; +import org.springframework.cloud.sleuth.trace.DefaultTraceManager; +import org.springframework.cloud.sleuth.trace.TraceContextHolder; +import org.springframework.context.support.StaticApplicationContext; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockFilterChain; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockServletContext; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; + +import java.util.Random; + +import static org.junit.Assert.assertNull; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; + +/** + * @author Spencer Gibb + * @author Dave Syer + */ +public class TraceFilterMockChainIntegrationTests { + + private StaticApplicationContext context = new StaticApplicationContext(); + + private TraceManager traceManager = new DefaultTraceManager(new AlwaysSampler(), + new Random(), this.context); + + private MockHttpServletRequest request; + private MockHttpServletResponse response; + private MockFilterChain filterChain; + + @Before + @SneakyThrows + public void init() { + TraceContextHolder.removeCurrentTrace(); + this.context.refresh(); + this.request = builder().buildRequest(new MockServletContext()); + this.response = new MockHttpServletResponse(); + this.response.setContentType(MediaType.APPLICATION_JSON_VALUE); + this.filterChain = new MockFilterChain(); + } + + public MockHttpServletRequestBuilder builder() { + return get("/").accept(MediaType.APPLICATION_JSON) + .header("User-Agent", "MockMvc"); + } + + @Test + public void startsNewTrace() throws Exception { + TraceFilter filter = new TraceFilter(this.traceManager); + filter.doFilter(this.request, this.response, this.filterChain); + assertNull(TraceContextHolder.getCurrentTrace()); + } + + @Test + public void continuesSpanFromHeaders() throws Exception { + Random generator = new Random(); + this.request = builder().header(Trace.SPAN_ID_NAME, generator.nextLong()) + .header(Trace.TRACE_ID_NAME, generator.nextLong()).buildRequest(new MockServletContext()); + TraceFilter filter = new TraceFilter(this.traceManager); + filter.doFilter(this.request, this.response, this.filterChain); + assertNull(TraceContextHolder.getCurrentSpan()); + } + +} 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 c95ffffd7..ee4a0fc8b 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,12 +16,7 @@ package org.springframework.cloud.sleuth.instrument.web; -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 lombok.SneakyThrows; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -41,9 +36,14 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; -import org.springframework.util.JdkIdGenerator; -import lombok.SneakyThrows; +import java.util.Random; + +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 @@ -66,8 +66,7 @@ public class TraceFilterTests { @SneakyThrows public void init() { initMocks(this); - this.traceManager = new DefaultTraceManager(new DelegateSampler(), - new JdkIdGenerator(), this.publisher) { + this.traceManager = new DefaultTraceManager(new DelegateSampler(), new Random(), this.publisher) { @Override protected Trace createTrace(Trace trace, Span span) { TraceFilterTests.this.span = span; @@ -123,8 +122,8 @@ public class TraceFilterTests { @Test public void continuesSpanFromHeaders() throws Exception { - this.request = builder().header(Trace.SPAN_ID_NAME, "myspan") - .header(Trace.TRACE_ID_NAME, "mytrace") + this.request = builder().header(Trace.SPAN_ID_NAME, 10L) + .header(Trace.TRACE_ID_NAME, 20L) .buildRequest(new MockServletContext()); TraceFilter filter = new TraceFilter(this.traceManager); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/FeignTraceTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/FeignTraceTests.java index 770c3b37a..7b110cf01 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/FeignTraceTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/FeignTraceTests.java @@ -1,11 +1,8 @@ package org.springframework.cloud.sleuth.instrument.web.client; -import static org.assertj.core.api.BDDAssertions.then; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - +import com.netflix.loadbalancer.BaseLoadBalancer; +import com.netflix.loadbalancer.ILoadBalancer; +import com.netflix.loadbalancer.Server; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -18,6 +15,7 @@ import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.cloud.netflix.ribbon.RibbonClient; import org.springframework.cloud.sleuth.MilliSpan; +import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; import org.springframework.cloud.sleuth.TraceManager; import org.springframework.cloud.sleuth.event.ClientReceivedEvent; @@ -31,15 +29,17 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.JdkIdGenerator; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; -import com.netflix.loadbalancer.BaseLoadBalancer; -import com.netflix.loadbalancer.ILoadBalancer; -import com.netflix.loadbalancer.Server; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +import static org.assertj.core.api.BDDAssertions.then; @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { FeignTraceTests.TestConfiguration.class }) @@ -75,8 +75,8 @@ public class FeignTraceTests { @Test public void shouldAttachTraceIdWhenUsingFeignClient() { // given - String currentTraceId = "currentTraceId"; - String currentParentId = "currentParentId"; + Long currentTraceId = 1L; + Long currentParentId = 2L; this.traceManager.continueSpan(MilliSpan.builder().traceId(currentTraceId) .spanId(generatedId()).parent(currentParentId).build()); @@ -84,12 +84,12 @@ public class FeignTraceTests { ResponseEntity response = this.testFeignInterface.getTraceId(); // then - then(getHeader(response, Trace.TRACE_ID_NAME)).isEqualTo(currentTraceId); + then(Span.IdConverter.fromHex(getHeader(response, Trace.TRACE_ID_NAME))).isEqualTo(currentTraceId); then(this.listener.getEvents().size()).isEqualTo(2); } - private String generatedId() { - return new JdkIdGenerator().generateId().toString(); + private Long generatedId() { + return new Random().nextLong(); } private String getHeader(ResponseEntity response, String name) { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorTests.java index 6737e121b..4f85fe6ba 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptorTests.java @@ -16,13 +16,6 @@ package org.springframework.cloud.sleuth.instrument.web.client; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -37,12 +30,19 @@ import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.test.web.client.MockMvcClientHttpRequestFactory; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.util.JdkIdGenerator; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import static org.assertj.core.api.BDDAssertions.then; +import static org.junit.Assert.assertFalse; + /** * @author Dave Syer * @@ -62,8 +62,7 @@ public class TraceRestTemplateInterceptorTests { @Before public void setup() { this.publisher.refresh(); - this.traces = new DefaultTraceManager(new AlwaysSampler(), - new JdkIdGenerator(), this.publisher); + this.traces = new DefaultTraceManager(new AlwaysSampler(), new Random(), this.publisher); this.template.setInterceptors(Arrays.asList( new TraceRestTemplateInterceptor(this.traces))); TraceContextHolder.removeCurrentTrace(); @@ -76,12 +75,12 @@ public class TraceRestTemplateInterceptorTests { @Test public void headersAddedWhenTracing() { - this.traces.continueSpan(MilliSpan.builder().traceId("foo").spanId("bar").build()); + this.traces.continueSpan(MilliSpan.builder().traceId(1L).spanId(2L).build()); @SuppressWarnings("unchecked") Map headers = this.template.getForEntity("/", Map.class) .getBody(); - assertEquals("bar", headers.get(Trace.SPAN_ID_NAME)); - assertEquals("foo", headers.get(Trace.TRACE_ID_NAME)); + then(Long.valueOf(headers.get(Trace.TRACE_ID_NAME))).isEqualTo(1L); + then(Long.valueOf(headers.get(Trace.SPAN_ID_NAME))).isEqualTo(2L); } @Test diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/JsonLogSpanListenerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/JsonLogSpanListenerTests.java index 1f36628d1..f8ad2a534 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/JsonLogSpanListenerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/JsonLogSpanListenerTests.java @@ -40,9 +40,9 @@ public class JsonLogSpanListenerTests { JsonLogSpanListener listener = new JsonLogSpanListener(); Span span = MilliSpan.builder() .name("testSpan") - .spanId("spanId1") - .parent("parentId1") - .traceId("traceId1") + .spanId(1L) + .parent(2L) + .traceId(3L) .begin(1) .end(10) .build(); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/DefaultStringToUuidConverterTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/DefaultStringToUuidConverterTests.java deleted file mode 100644 index 90e2d7618..000000000 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/DefaultStringToUuidConverterTests.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.springframework.cloud.sleuth.sampler; - -import org.junit.Test; - -import java.util.UUID; - -import static org.assertj.core.api.BDDAssertions.then; - -public class DefaultStringToUuidConverterTests { - - DefaultStringToUuidConverter defaultStringToUuidConverter = new DefaultStringToUuidConverter(); - - @Test - public void should_successfully_convert_string_to_uuid_and_increment_success_counter() throws Exception { - UUID expectedUuid = UUID.randomUUID(); - String uuidAsString = expectedUuid.toString(); - - UUID convertedUuid = defaultStringToUuidConverter.convert(uuidAsString); - - then(convertedUuid).isEqualTo(expectedUuid); - } - - @Test - public void should_fail_to_convert_string_to_uuid_and_increment_failures_counter() throws Exception { - String invalidUuidString = "non UUID format string"; - - UUID convertedUuid = defaultStringToUuidConverter.convert(invalidUuidString); - - then(convertedUuid).isNull(); - } -} \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/PercentageBasedSamplerTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/PercentageBasedSamplerTests.java index 46c9989b0..fc766b7a5 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/PercentageBasedSamplerTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/PercentageBasedSamplerTests.java @@ -9,18 +9,21 @@ import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.TraceAccessor; import org.springframework.util.JdkIdGenerator; +import java.util.Random; +import java.util.stream.Stream; + public class PercentageBasedSamplerTests { SamplerConfiguration samplerConfiguration = new SamplerConfiguration(); TraceAccessor traceAccessor = traceReturningSpanWithUuid(); - StringToUuidConverter stringToUuidConverter = new DefaultStringToUuidConverter(); + private static Random RANDOM = new Random(); @Test public void should_pass_all_samples_when_config_has_1_percentage() throws Exception { this.samplerConfiguration.setPercentage(1f); for (int i = 0; i < 10; i++) { - then(new PercentageBasedSampler(this.samplerConfiguration, this.traceAccessor, this.stringToUuidConverter).next(null)).isTrue(); + then(new PercentageBasedSampler(this.samplerConfiguration, this.traceAccessor).next(null)).isTrue(); } } @@ -30,19 +33,10 @@ public class PercentageBasedSamplerTests { this.samplerConfiguration.setPercentage(0f); for (int i = 0; i < 10; i++) { - then(new PercentageBasedSampler(this.samplerConfiguration, this.traceAccessor, this.stringToUuidConverter).next(null)).isFalse(); + then(new PercentageBasedSampler(this.samplerConfiguration, this.traceAccessor).next(null)).isFalse(); } } - @Test - public void should_reject_sample_when_trace_id_is_invalid() throws Exception { - this.samplerConfiguration.setPercentage(1f); - - boolean passed = new PercentageBasedSampler(this.samplerConfiguration, traceReturningSpanWithInvalidUuid(), this.stringToUuidConverter).next(null); - - then(passed).isFalse(); - } - @Test public void should_pass_given_percent_of_samples() throws Exception { int numberOfIterations = 10000; @@ -57,7 +51,7 @@ public class PercentageBasedSamplerTests { private int countNumberOfSampledElements(int numberOfIterations) { int passedCounter = 0; for (int i = 0; i < numberOfIterations; i++) { - boolean passed = new PercentageBasedSampler(this.samplerConfiguration, traceReturningSpanWithUuid(), this.stringToUuidConverter).next(null); + boolean passed = new PercentageBasedSampler(this.samplerConfiguration, traceReturningSpanWithUuid()).next(null); passedCounter = passedCounter + (passed ? 1 : 0); } return passedCounter; @@ -67,21 +61,7 @@ public class PercentageBasedSamplerTests { return new TraceAccessor() { @Override public Span getCurrentSpan() { - return MilliSpan.builder().traceId(new JdkIdGenerator().generateId().toString()).build(); - } - - @Override - public boolean isTracing() { - return true; - } - }; - } - - private TraceAccessor traceReturningSpanWithInvalidUuid() { - return new TraceAccessor() { - @Override - public Span getCurrentSpan() { - return MilliSpan.builder().traceId("invalid uuid").build(); + return MilliSpan.builder().traceId(RANDOM.nextLong()).build(); } @Override diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/UuidTraceIdToThresholdComparableTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/UuidTraceIdToThresholdComparableTests.java deleted file mode 100644 index beb63e120..000000000 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/UuidTraceIdToThresholdComparableTests.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.springframework.cloud.sleuth.sampler; - -import org.junit.Test; - -import java.util.UUID; -import java.util.stream.Stream; - -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.data.Percentage.withPercentage; - -public class UuidTraceIdToThresholdComparableTests { - - final UUID[] traceIds = createRandomUuids(); - - @Test - public void should_retain_10_percent() { - float sampleRate = 0.1f; - UuidTraceIdToThresholdComparable sampler = new UuidTraceIdToThresholdComparable(sampleRate); - - long passCount = Stream.of(traceIds).filter(uuid -> smallerThanThreshold(sampler, uuid)).count(); - - then(passCount) - .isCloseTo((long) (traceIds.length * sampleRate), withPercentage(3)); - } - - @Test - public void should_be_idempotent() { - UuidTraceIdToThresholdComparable sampler1 = new UuidTraceIdToThresholdComparable(0.1f); - UuidTraceIdToThresholdComparable sampler2 = new UuidTraceIdToThresholdComparable(0.1f); - - then(Stream.of(traceIds).filter(uuid -> smallerThanThreshold(sampler1, uuid)).toArray()) - .containsExactly(Stream.of(traceIds).filter(uuid -> smallerThanThreshold(sampler2, uuid)).toArray()); - } - - @Test - public void should_have_127_bit_number_as_max_long() { - then(UuidTraceIdToThresholdComparable.MAX_128.toString(2)).matches("^1+$").hasSize(127); - } - - private boolean smallerThanThreshold(UuidTraceIdToThresholdComparable comparable, UUID traceId) { - return comparable.compareTo(traceId.toString()) == -1; - } - - private UUID[] createRandomUuids() { - UUID[] traceIds; - traceIds = new UUID[100000]; - for (int i = 0; i < traceIds.length; i++) { - traceIds[i] = UUID.randomUUID(); - } - return traceIds; - } - -} \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/template/TraceTemplateTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/template/TraceTemplateTests.java index d3d51e437..c5290d0c8 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/template/TraceTemplateTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/template/TraceTemplateTests.java @@ -8,13 +8,15 @@ import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.cloud.sleuth.trace.DefaultTraceManager; import org.springframework.cloud.sleuth.trace.TraceContextHolder; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.util.JdkIdGenerator; + +import java.util.Random; import static org.assertj.core.api.BDDAssertions.then; public class TraceTemplateTests { - TraceManager traceManager = new DefaultTraceManager(new AlwaysSampler(), new JdkIdGenerator(), Mockito.mock(ApplicationEventPublisher.class)); + TraceManager traceManager = new DefaultTraceManager(new AlwaysSampler(), + new Random(), Mockito.mock(ApplicationEventPublisher.class)); @Test public void should_pass_trace_to_the_callback_if_tracing_is_active() { diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java index 92adebffa..61152ba4e 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleBackground.java @@ -32,11 +32,12 @@ public class SampleBackground { @Autowired private TraceManager traceManager; + @Autowired + private Random random; @SneakyThrows @Async public void background() { - final Random random = new Random(); int millis = random.nextInt(1000); Thread.sleep(millis); this.traceManager.addAnnotation("background-sleep-millis", String.valueOf(millis)); 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 0d75747d6..16e40cb84 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 @@ -27,11 +27,11 @@ 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 org.springframework.util.JdkIdGenerator; import sample.SampleMessagingApplication; import tools.AbstractIntegrationTest; import java.util.Collection; +import java.util.Random; import static org.assertj.core.api.BDDAssertions.then; @@ -52,7 +52,7 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { @Test public void should_propagate_spans_for_messaging() { - String traceId = new JdkIdGenerator().generateId().toString(); + long traceId = new Random().nextLong(); await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/", traceId)); @@ -63,7 +63,7 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { @Test public void should_propagate_spans_for_messaging_with_async() { - String traceId = new JdkIdGenerator().generateId().toString(); + long traceId = new Random().nextLong(); await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/xform", traceId)); @@ -80,8 +80,8 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { .anyMatch(b -> b.key.equals(binaryAnnotationKey))).isTrue(); } - private void thenAllSpansHaveTraceIdEqualTo(String traceId) { - then(integrationTestSpanCollector.hashedSpans.stream().allMatch(span -> span.traceId == zipkinHashedTraceId(traceId))).isTrue(); + private void thenAllSpansHaveTraceIdEqualTo(long traceId) { + then(this.integrationTestSpanCollector.hashedSpans.stream().allMatch(span -> span.traceId == traceId)).isTrue(); } @Configuration diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleController.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleController.java index 6e496b248..70d02c294 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleController.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-ribbon/src/main/java/sample/SampleController.java @@ -16,15 +16,14 @@ package sample; -import java.util.Random; - import lombok.SneakyThrows; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; +import java.util.Random; + /** * @author Spencer Gibb * @author Dave Syer @@ -34,11 +33,12 @@ public class SampleController { @Autowired private RestTemplate restTemplate; + @Autowired + private Random random; @SneakyThrows @RequestMapping("/") public String hi() { - final Random random = new Random(); Thread.sleep(random.nextInt(1000)); String s = this.restTemplate.getForObject("http://zipkin/hi2", String.class); return "hi/" + s; 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 3183d56ec..38de64a39 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,9 +16,8 @@ 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; @@ -31,8 +30,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; +import java.util.Random; +import java.util.concurrent.Callable; /** * @author Spencer Gibb @@ -49,12 +48,13 @@ ApplicationListener { private TraceAccessor accessor; @Autowired private SampleBackground controller; + @Autowired + private Random random; private int port; @SneakyThrows @RequestMapping("/") public String hi() { - final Random random = new Random(); Thread.sleep(random.nextInt(1000)); String s = this.restTemplate.getForObject("http://localhost:" + this.port @@ -67,7 +67,6 @@ ApplicationListener { return new Callable() { @Override public String call() throws Exception { - final Random random = new Random(); int millis = random.nextInt(1000); Thread.sleep(millis); SampleController.this.traceManager.addAnnotation("callable-sleep-millis", String.valueOf(millis)); @@ -86,7 +85,6 @@ ApplicationListener { @SneakyThrows @RequestMapping("/hi2") public String hi2() { - final Random random = new Random(); int millis = random.nextInt(1000); Thread.sleep(millis); this.traceManager.addAnnotation("random-sleep-millis", String.valueOf(millis)); @@ -98,7 +96,6 @@ ApplicationListener { public String traced() { Trace trace = this.traceManager.startSpan("customTraceEndpoint", new AlwaysSampler(), null); - final Random random = new Random(); int millis = random.nextInt(1000); log.info("Sleeping for {} millis", millis); Thread.sleep(millis); @@ -113,7 +110,6 @@ ApplicationListener { @SneakyThrows @RequestMapping("/start") public String start() { - final Random random = new Random(); int millis = random.nextInt(1000); log.info("Sleeping for {} millis", millis); Thread.sleep(millis); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java index 74bcdd920..0223d7cb2 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java @@ -15,30 +15,20 @@ */ package tools; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.assertj.core.api.BDDAssertions.then; - -import java.net.URI; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; - import com.jayway.awaitility.Awaitility; import com.jayway.awaitility.core.ConditionFactory; - import io.zipkin.Codec; import io.zipkin.Span; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.*; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; +import java.util.*; +import java.util.stream.Collectors; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.assertj.core.api.BDDAssertions.then; /** * @author Marcin Grzejszczak @@ -47,31 +37,13 @@ import lombok.extern.slf4j.Slf4j; public abstract class AbstractIntegrationTest { protected static int pollInterval = 1; - protected static int timeout = 120; + protected static int timeout = 20; protected RestTemplate restTemplate = new AssertingRestTemplate(); public static ConditionFactory await() { return Awaitility.await().pollInterval(pollInterval, SECONDS).atMost(timeout, SECONDS); } - protected long zipkinHashedTraceId(String string) { - long h = 1125899906842597L; - if (string == null) { - return h; - } - int len = string.length(); - - for (int i = 0; i < len; i++) { - h = 31 * h + string.charAt(i); - } - return h; - } - - protected String zipkinHashedHexStringTraceId(String traceId) { - long hashedTraceId = zipkinHashedTraceId(traceId); - return Long.toHexString(hashedTraceId); - } - protected Runnable zipkinQueryServerIsUp() { return checkServerHealth("Zipkin Query Server", this::endpointToCheckZipkinQueryHealth); } @@ -109,10 +81,9 @@ public abstract class AbstractIntegrationTest { return 9411; } - protected ResponseEntity checkStateOfTheTraceId(String traceId) { - String hexTraceId = zipkinHashedHexStringTraceId(traceId); - URI uri = URI.create(getZipkinTraceQueryUrl() + hexTraceId); - log.info("Sending request to the Zipkin query service [{}]. Checking presence of trace id [{}] and its hex version [{}]", uri, traceId, hexTraceId); + protected ResponseEntity checkStateOfTheTraceId(long traceId) { + URI uri = URI.create(getZipkinTraceQueryUrl() + Long.toHexString(traceId)); + log.info("Sending request to the Zipkin query service [{}]. Checking presence of trace id [{}]", uri, traceId); return exchangeRequest(uri); } @@ -130,11 +101,11 @@ public abstract class AbstractIntegrationTest { return "http://localhost:"+getZipkinServerPort()+"/api/v1/services"; } - protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, String traceId) { + protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, long traceId) { return new RequestSendingRunnable(this.restTemplate, endpoint, traceId); } - protected Runnable allSpansWereRegisteredInZipkinWithTraceIdEqualTo(String traceId) { + protected Runnable allSpansWereRegisteredInZipkinWithTraceIdEqualTo(long traceId) { return () -> { ResponseEntity response = checkStateOfTheTraceId(traceId); log.info("Response from the Zipkin query service about the trace id [{}] for trace with id [{}]", response, traceId); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java index b16f73fc7..61ac8e400 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java @@ -16,6 +16,7 @@ package tools; import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Trace; import org.springframework.http.*; import org.springframework.web.client.RestTemplate; @@ -34,9 +35,9 @@ import static org.assertj.core.api.BDDAssertions.then; public class RequestSendingRunnable implements Runnable { private final RestTemplate restTemplate; private final String url; - private final String traceId; + private final long traceId; - public RequestSendingRunnable(RestTemplate restTemplate, String url, String traceId) { + public RequestSendingRunnable(RestTemplate restTemplate, String url, long traceId) { this.restTemplate = restTemplate; this.url = url; this.traceId = traceId; @@ -50,9 +51,9 @@ public class RequestSendingRunnable implements Runnable { log.info("Received the following response [{}]", responseEntity); } - private RequestEntity requestWithTraceId(String traceId) { + private RequestEntity requestWithTraceId(long traceId) { HttpHeaders headers = new HttpHeaders(); - headers.add(Trace.TRACE_ID_NAME, traceId); + headers.add(Trace.TRACE_ID_NAME, Span.IdConverter.toHex(traceId)); URI uri = URI.create(url); RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, uri); log.info("Request [" + requestEntity + "] is ready"); 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 9ff944c37..7b565aa5f 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,8 +15,8 @@ */ package integration; -import java.util.Arrays; - +import example.ZipkinStreamServerApplication; +import lombok.SneakyThrows; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -34,12 +34,11 @@ import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.MessageChannel; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.JdkIdGenerator; - -import example.ZipkinStreamServerApplication; -import lombok.SneakyThrows; import tools.AbstractIntegrationTest; +import java.util.Collections; +import java.util.Random; + @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { TestSupportBinderAutoConfiguration.class, ZipkinStreamServerApplication.class }) @@ -60,13 +59,13 @@ public class ZipkinStreamTests extends AbstractIntegrationTest { await().until(zipkinServerIsUp()); - String traceId = new JdkIdGenerator().generateId().toString(); + long traceId = new Random().nextLong(); Span span = MilliSpan.builder().traceId(traceId).spanId(traceId).name("test") .build(); span.tag(getRequiredBinaryAnnotationName(), "10131"); this.input.send(MessageBuilder.withPayload( - new Spans(new Host(getAppName(), "127.0.0.1", 8080), Arrays.asList(span))) + new Spans(new Host(getAppName(), "127.0.0.1", 8080), Collections.singletonList(span))) .build()); await().until(allSpansWereRegisteredInZipkinWithTraceIdEqualTo(traceId)); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleBackground.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleBackground.java index d7d1fa6d7..61152ba4e 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleBackground.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/main/java/sample/SampleBackground.java @@ -16,15 +16,14 @@ package sample; -import java.util.Random; - import lombok.SneakyThrows; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.sleuth.TraceManager; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; +import java.util.Random; + /** * @author Spencer Gibb */ @@ -33,11 +32,12 @@ public class SampleBackground { @Autowired private TraceManager traceManager; + @Autowired + private Random random; @SneakyThrows @Async public void background() { - final Random random = new Random(); int millis = random.nextInt(1000); Thread.sleep(millis); this.traceManager.addAnnotation("background-sleep-millis", String.valueOf(millis)); 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 3183d56ec..38de64a39 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 @@ -16,9 +16,8 @@ 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; @@ -31,8 +30,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; +import java.util.Random; +import java.util.concurrent.Callable; /** * @author Spencer Gibb @@ -49,12 +48,13 @@ ApplicationListener { private TraceAccessor accessor; @Autowired private SampleBackground controller; + @Autowired + private Random random; private int port; @SneakyThrows @RequestMapping("/") public String hi() { - final Random random = new Random(); Thread.sleep(random.nextInt(1000)); String s = this.restTemplate.getForObject("http://localhost:" + this.port @@ -67,7 +67,6 @@ ApplicationListener { return new Callable() { @Override public String call() throws Exception { - final Random random = new Random(); int millis = random.nextInt(1000); Thread.sleep(millis); SampleController.this.traceManager.addAnnotation("callable-sleep-millis", String.valueOf(millis)); @@ -86,7 +85,6 @@ ApplicationListener { @SneakyThrows @RequestMapping("/hi2") public String hi2() { - final Random random = new Random(); int millis = random.nextInt(1000); Thread.sleep(millis); this.traceManager.addAnnotation("random-sleep-millis", String.valueOf(millis)); @@ -98,7 +96,6 @@ ApplicationListener { public String traced() { Trace trace = this.traceManager.startSpan("customTraceEndpoint", new AlwaysSampler(), null); - final Random random = new Random(); int millis = random.nextInt(1000); log.info("Sleeping for {} millis", millis); Thread.sleep(millis); @@ -113,7 +110,6 @@ ApplicationListener { @SneakyThrows @RequestMapping("/start") public String start() { - final Random random = new Random(); int millis = random.nextInt(1000); log.info("Sleeping for {} millis", millis); Thread.sleep(millis); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinTests.java index f22174b06..7d38bbec2 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinTests.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin/src/test/java/integration/ZipkinTests.java @@ -31,10 +31,11 @@ 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 org.springframework.util.JdkIdGenerator; import sample.SampleZipkinApplication; import tools.AbstractIntegrationTest; +import java.util.Random; + @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = { WaitUntilZipkinIsUpConfig.class, SampleZipkinApplication.class }) @@ -53,9 +54,8 @@ public class ZipkinTests extends AbstractIntegrationTest { } @Test - @SneakyThrows public void should_propagate_spans_to_zipkin() { - String traceId = new JdkIdGenerator().generateId().toString(); + long traceId = new Random().nextLong(); await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent( sampleAppUrl + "/hi2", traceId)); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleBackground.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleBackground.java index d7d1fa6d7..61152ba4e 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleBackground.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample/src/main/java/sample/SampleBackground.java @@ -16,15 +16,14 @@ package sample; -import java.util.Random; - import lombok.SneakyThrows; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.sleuth.TraceManager; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; +import java.util.Random; + /** * @author Spencer Gibb */ @@ -33,11 +32,12 @@ public class SampleBackground { @Autowired private TraceManager traceManager; + @Autowired + private Random random; @SneakyThrows @Async public void background() { - final Random random = new Random(); int millis = random.nextInt(1000); Thread.sleep(millis); this.traceManager.addAnnotation("background-sleep-millis", String.valueOf(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 3183d56ec..38de64a39 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,9 +16,8 @@ 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; @@ -31,8 +30,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; -import lombok.SneakyThrows; -import lombok.extern.slf4j.Slf4j; +import java.util.Random; +import java.util.concurrent.Callable; /** * @author Spencer Gibb @@ -49,12 +48,13 @@ ApplicationListener { private TraceAccessor accessor; @Autowired private SampleBackground controller; + @Autowired + private Random random; private int port; @SneakyThrows @RequestMapping("/") public String hi() { - final Random random = new Random(); Thread.sleep(random.nextInt(1000)); String s = this.restTemplate.getForObject("http://localhost:" + this.port @@ -67,7 +67,6 @@ ApplicationListener { return new Callable() { @Override public String call() throws Exception { - final Random random = new Random(); int millis = random.nextInt(1000); Thread.sleep(millis); SampleController.this.traceManager.addAnnotation("callable-sleep-millis", String.valueOf(millis)); @@ -86,7 +85,6 @@ ApplicationListener { @SneakyThrows @RequestMapping("/hi2") public String hi2() { - final Random random = new Random(); int millis = random.nextInt(1000); Thread.sleep(millis); this.traceManager.addAnnotation("random-sleep-millis", String.valueOf(millis)); @@ -98,7 +96,6 @@ ApplicationListener { public String traced() { Trace trace = this.traceManager.startSpan("customTraceEndpoint", new AlwaysSampler(), null); - final Random random = new Random(); int millis = random.nextInt(1000); log.info("Sleeping for {} millis", millis); Thread.sleep(millis); @@ -113,7 +110,6 @@ ApplicationListener { @SneakyThrows @RequestMapping("/start") public String start() { - final Random random = new Random(); int millis = random.nextInt(1000); log.info("Sleeping for {} millis", millis); Thread.sleep(millis); diff --git a/spring-cloud-sleuth-stream/src/main/java/org/springframework/cloud/sleuth/stream/ServerPropertiesHostLocator.java b/spring-cloud-sleuth-stream/src/main/java/org/springframework/cloud/sleuth/stream/ServerPropertiesHostLocator.java index c3ea0984e..8dfc8afcd 100644 --- a/spring-cloud-sleuth-stream/src/main/java/org/springframework/cloud/sleuth/stream/ServerPropertiesHostLocator.java +++ b/spring-cloud-sleuth-stream/src/main/java/org/springframework/cloud/sleuth/stream/ServerPropertiesHostLocator.java @@ -80,8 +80,8 @@ public class ServerPropertiesHostLocator implements HostLocator { private String getServiceName(Span span) { String serviceName; - if (span.getProcessId() != null) { // TODO: javadocs say this isn't nullable! - serviceName = span.getProcessId().toLowerCase(); + if (span.getProcessId() != null) { + serviceName = span.getProcessId(); } else { serviceName = this.appName; 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 1b3aafa81..9d76e5c5c 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,17 +16,18 @@ package org.springframework.cloud.sleuth.stream; -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.MilliSpan; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Collections; + import static org.assertj.core.api.Assertions.assertThat; public class ServerPropertiesHostLocatorTests { - MilliSpan span = new MilliSpan(1, 3, "name", "traceId", Collections.emptyList(), "spanId", true, true, "processId"); + MilliSpan span = new MilliSpan(1, 3, "name", 1L, Collections.emptyList(), 2L, true, true, "process"); @Test public void portDefaultsTo8080() { 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 08280bfcf..4876fea05 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 @@ -85,7 +85,7 @@ public class StreamSpanListenerTests { @Test public void rpcAnnotations() { - Span parent = MilliSpan.builder().traceId("xxxx").name("parent").remote(true) + Span parent = MilliSpan.builder().traceId(1L).name("parent").remote(true) .build(); Trace context = this.traceManager.startSpan("child", parent); this.application.publishEvent(new ClientSentEvent(this, context.getSpan())); diff --git a/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListener.java b/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListener.java index 4a7e0babc..b407ffc11 100644 --- a/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListener.java +++ b/spring-cloud-sleuth-zipkin-stream/src/main/java/org/springframework/cloud/sleuth/zipkin/stream/ZipkinMessageListener.java @@ -1,13 +1,9 @@ package org.springframework.cloud.sleuth.zipkin.stream; -import io.zipkin.Sampler; -import java.io.UnsupportedEncodingException; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; - -import javax.sql.DataSource; - +import io.zipkin.*; +import io.zipkin.BinaryAnnotation.Type; +import io.zipkin.Span.Builder; +import lombok.extern.apachecommons.CommonsLog; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionOutcome; @@ -16,17 +12,13 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.Cloud; import org.springframework.cloud.CloudFactory; -import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Log; +import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.stream.Host; import org.springframework.cloud.sleuth.stream.SleuthSink; import org.springframework.cloud.sleuth.stream.Spans; import org.springframework.cloud.sleuth.zipkin.stream.ZipkinMessageListener.NotSleuthStreamClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ConditionContext; -import org.springframework.context.annotation.Conditional; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.*; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; import org.springframework.core.env.MapPropertySource; @@ -35,20 +27,19 @@ import org.springframework.integration.annotation.MessageEndpoint; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.util.StringUtils; -import io.zipkin.Annotation; -import io.zipkin.BinaryAnnotation; -import io.zipkin.BinaryAnnotation.Type; -import io.zipkin.Constants; -import io.zipkin.Endpoint; -import io.zipkin.Span.Builder; -import io.zipkin.SpanStore; -import lombok.extern.apachecommons.CommonsLog; +import javax.sql.DataSource; +import java.io.UnsupportedEncodingException; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; @MessageEndpoint @CommonsLog @Conditional(NotSleuthStreamClient.class) public class ZipkinMessageListener { + private static final String UNKNOWN_PROCESS_ID = "unknown"; + @Autowired SpanStore spanStore; @@ -80,10 +71,9 @@ public class ZipkinMessageListener { // A zipkin span without any annotations cannot be queried, add special "lc" to avoid that. if (span.logs().isEmpty() && span.tags().isEmpty()) { - // TODO: javadocs say this isn't nullable! String processId = span.getProcessId() != null ? span.getProcessId().toLowerCase() - : "unknown"; + : UNKNOWN_PROCESS_ID; zipkinSpan.addBinaryAnnotation( BinaryAnnotation.create(Constants.LOCAL_COMPONENT, processId, ep) ); @@ -94,15 +84,15 @@ public class ZipkinMessageListener { zipkinSpan.timestamp(span.getBegin() * 1000); zipkinSpan.duration((span.getEnd() - span.getBegin()) * 1000); - zipkinSpan.traceId(hash(span.getTraceId())); + zipkinSpan.traceId(span.getTraceId()); if (span.getParents().size() > 0) { if (span.getParents().size() > 1) { log.error("zipkin doesn't support spans with multiple parents. Omitting " + "other parents for " + span); } - zipkinSpan.parentId(hash(span.getParents().get(0))); + zipkinSpan.parentId(span.getParents().get(0)); } - zipkinSpan.id(hash(span.getSpanId())); + zipkinSpan.id(span.getSpanId()); if (StringUtils.hasText(span.getName())) { zipkinSpan.name(span.getName()); } @@ -145,19 +135,6 @@ public class ZipkinMessageListener { } } - private static long hash(String string) { - long h = 1125899906842597L; - if (string == null) { - return h; - } - int len = string.length(); - - for (int i = 0; i < len; i++) { - h = 31 * h + string.charAt(i); - } - return h; - } - protected static class NotSleuthStreamClient extends SpringBootCondition { @Override 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 884c16ae8..6c50c1b39 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 @@ -16,17 +16,18 @@ package org.springframework.cloud.sleuth.zipkin.stream; import io.zipkin.Sampler; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import org.springframework.cloud.sleuth.MilliSpan; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.stream.Host; import org.springframework.cloud.sleuth.stream.Spans; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; + import static org.assertj.core.api.Assertions.assertThat; public class SamplingZipkinSpanIteratorTests { @@ -69,7 +70,7 @@ public class SamplingZipkinSpanIteratorTests { } Span span(String name) { - String id = UUID.randomUUID().toString(); - return new MilliSpan(1, 3, name, id, Collections.emptyList(), id, true, true, "proc"); + Long id = new Random().nextLong(); + return new MilliSpan(1, 3, 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 5574302ed..1172c1c38 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 @@ -19,8 +19,6 @@ package org.springframework.cloud.sleuth.zipkin.stream; import io.zipkin.BinaryAnnotation; import io.zipkin.Endpoint; import java.util.Collections; -import java.util.Comparator; -import java.util.Objects; import org.junit.Test; import org.springframework.cloud.sleuth.MilliSpan; @@ -29,7 +27,7 @@ import org.springframework.cloud.sleuth.stream.Host; import static org.assertj.core.api.Assertions.assertThat; public class ZipkinMessageListenerTests { - MilliSpan span = new MilliSpan(1, 3, "name", "traceId", Collections.emptyList(), "spanId", true, true, "processId"); + MilliSpan span = new MilliSpan(1, 3, "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); @@ -75,13 +73,13 @@ public class ZipkinMessageListenerTests { assertThat(result.binaryAnnotations).hasSize(1); assertThat(result.binaryAnnotations.get(0)).isEqualToComparingFieldByField( - BinaryAnnotation.create("lc", span.getProcessId().toLowerCase(), endpoint)); + BinaryAnnotation.create("lc", span.getProcessId(), endpoint)); } // TODO: "unknown" bc process id, documented as not nullable, is null in some tests. @Test public void nullProcessIdCoercesToUnknownServiceName() { - MilliSpan noProcessId = MilliSpan.builder().traceId("xxxx").name("parent").remote(true).build(); + MilliSpan noProcessId = MilliSpan.builder().traceId(1L).name("parent").remote(true).build(); io.zipkin.Span result = ZipkinMessageListener.convert(noProcessId, 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 b9d3bbfaf..a69704ecb 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 @@ -16,11 +16,13 @@ package org.springframework.cloud.sleuth.zipkin; -import java.nio.charset.Charset; -import java.util.Map; - -import org.springframework.cloud.sleuth.Span; +import io.zipkin.Annotation; +import io.zipkin.BinaryAnnotation; +import io.zipkin.Constants; +import io.zipkin.Endpoint; +import lombok.extern.apachecommons.CommonsLog; import org.springframework.cloud.sleuth.Log; +import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.event.ClientReceivedEvent; import org.springframework.cloud.sleuth.event.ClientSentEvent; import org.springframework.cloud.sleuth.event.ServerReceivedEvent; @@ -31,12 +33,8 @@ import org.springframework.context.event.EventListener; import org.springframework.core.annotation.Order; import org.springframework.util.StringUtils; -import io.zipkin.Annotation; -import io.zipkin.BinaryAnnotation; -import io.zipkin.Constants; -import io.zipkin.Endpoint; - -import lombok.extern.apachecommons.CommonsLog; +import java.nio.charset.Charset; +import java.util.Map; /** * @author Spencer Gibb @@ -126,7 +124,6 @@ public class ZipkinSpanListener { // A zipkin span without any annotations cannot be queried, add special "lc" to avoid that. if (span.logs().isEmpty() && span.tags().isEmpty()) { - // TODO: javadocs say this isn't nullable! byte[] processId = span.getProcessId() != null ? span.getProcessId().toLowerCase().getBytes(UTF_8) : UNKNOWN_BYTES; @@ -143,15 +140,15 @@ public class ZipkinSpanListener { zipkinSpan.timestamp(span.getBegin() * 1000L); zipkinSpan.duration((span.getEnd() - span.getBegin()) * 1000L); - zipkinSpan.traceId(hash(span.getTraceId())); + zipkinSpan.traceId(span.getTraceId()); if (span.getParents().size() > 0) { if (span.getParents().size() > 1) { log.error("Zipkin doesn't support spans with multiple parents. Omitting " + "other parents for " + span); } - zipkinSpan.parentId(hash(span.getParents().get(0))); + zipkinSpan.parentId(span.getParents().get(0)); } - zipkinSpan.id(hash(span.getSpanId())); + zipkinSpan.id(span.getSpanId()); if (StringUtils.hasText(span.getName())) { zipkinSpan.name(span.getName()); } @@ -189,17 +186,4 @@ public class ZipkinSpanListener { } } - private static long hash(String string) { - long h = 1125899906842597L; - if (string == null) { - return h; - } - int len = string.length(); - - for (int i = 0; i < len; i++) { - h = 31 * h + string.charAt(i); - } - return h; - } - } 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 b81ae452f..fb9c2584a 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 @@ -72,7 +72,7 @@ public class ZipkinSpanListenerTests { this.test.spans.clear(); } - Span parent = MilliSpan.builder().traceId("xxxx").name("parent").remote(true).build(); + Span parent = MilliSpan.builder().traceId(1L).name("parent").remote(true).build(); /** Sleuth timestamps are millisecond granularity while zipkin is microsecond. */ @Test