[#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
This commit is contained in:
@@ -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<String> parents = new ArrayList<>();
|
||||
private final String spanId;
|
||||
private List<Long> parents = new ArrayList<>();
|
||||
private final long spanId;
|
||||
private boolean remote = false;
|
||||
private boolean exportable = true;
|
||||
private final Map<String, String> 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<String> parents, String spanId, boolean remote, boolean exportable, String processId) {
|
||||
public MilliSpan(long begin, long end, String name, long traceId, List<Long> 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
|
||||
|
||||
@@ -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.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* 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 {
|
||||
* <p/>
|
||||
* The collection will be empty if there are no parents.
|
||||
*/
|
||||
List<String> getParents();
|
||||
List<Long> 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<Log> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Void> sampler, IdGenerator idGenerator,
|
||||
public DefaultTraceManager traceManager(Sampler<Void> sampler,
|
||||
ApplicationEventPublisher publisher) {
|
||||
return new DefaultTraceManager(sampler, idGenerator, publisher);
|
||||
return new DefaultTraceManager(sampler, random(), publisher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> T getHeader(Message<?> message, String name, Class<T> type) {
|
||||
return message.getHeaders().get(name, type);
|
||||
}
|
||||
|
||||
boolean hasHeader(Message<?> message, String name) {
|
||||
return message.getHeaders().containsKey(name);
|
||||
}
|
||||
|
||||
String getChannelName(MessageChannel channel) {
|
||||
|
||||
@@ -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<String, String> headers, String name,
|
||||
String value) {
|
||||
if (value != null) {
|
||||
if (StringUtils.hasText(value)) {
|
||||
headers.put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getFirst(List<String> parents) {
|
||||
return parents == null || parents.isEmpty() ? null : parents.get(0);
|
||||
private static void addHeader(Map<String, String> headers, String name,
|
||||
Long value) {
|
||||
if (value != null) {
|
||||
addHeader(headers, name, Span.IdConverter.toHex(value));
|
||||
}
|
||||
}
|
||||
|
||||
private static Long getFirst(List<Long> parents) {
|
||||
return parents.isEmpty() ? null : parents.get(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String> parents = currentSpan.getParents();
|
||||
return parents == null || parents.isEmpty() ? null : parents.get(0);
|
||||
private Long getParentId(final Span currentSpan) {
|
||||
List<Long> parents = currentSpan.getParents();
|
||||
return parents.isEmpty() ? null : parents.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Trace> traceHolder = new ThreadLocal<>();
|
||||
|
||||
public TraceChannelInterceptor(TraceManager traceManager) {
|
||||
super(traceManager);
|
||||
public TraceChannelInterceptor(TraceManager traceManager, Random random) {
|
||||
super(traceManager, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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<String, Object> headers, String name, long value) {
|
||||
setHeader(headers, name, Span.IdConverter.toHex(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPayload() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Trace> traceScopeHolder = new ThreadLocal<Trace>();
|
||||
|
||||
public TraceStompMessageChannelInterceptor(final TraceManager traceManager) {
|
||||
super(traceManager);
|
||||
public TraceStompMessageChannelInterceptor(TraceManager traceManager, Random random) {
|
||||
super(traceManager, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<String, Collection<String>> headersWithTraceId(
|
||||
Map<String, Collection<String>> headers) {
|
||||
Map<String, Collection<String>> 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<String, Collection<String>> 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<String, Collection<String>> headers, String name,
|
||||
Long value) {
|
||||
if (value != null ){
|
||||
setHeader(headers, name, Span.IdConverter.toHex(value));
|
||||
}
|
||||
}
|
||||
|
||||
private Span getCurrentSpan() {
|
||||
return this.accessor.getCurrentSpan();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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<String, String> request, String name, Long value) {
|
||||
setHeader(request, name, Span.IdConverter.toHex(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filterType() {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
@@ -26,22 +26,22 @@ public class PercentageBasedSampler implements Sampler<Void> {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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<Void> defaultSampler;
|
||||
|
||||
private final IdGenerator idGenerator;
|
||||
|
||||
private final ApplicationEventPublisher publisher;
|
||||
|
||||
public DefaultTraceManager(Sampler<Void> defaultSampler, IdGenerator idGenerator,
|
||||
ApplicationEventPublisher publisher) {
|
||||
private final Random random;
|
||||
|
||||
public DefaultTraceManager(Sampler<Void> 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
|
||||
|
||||
@@ -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<Span> spans, String parentId, String name) {
|
||||
private Span assertSpan(List<Span> spans, Long parentId, String name) {
|
||||
List<Span> 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<Span> findSpans(List<Span> spans, String parentId) {
|
||||
private List<Span> findSpans(List<Span> spans, Long parentId) {
|
||||
List<Span> found = new ArrayList<>();
|
||||
for (Span span : spans) {
|
||||
if (parentId == null && span.getParents().isEmpty()) {
|
||||
|
||||
@@ -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.<String>emptyList(), "spanId", true, true, "processId");
|
||||
MilliSpan span = new MilliSpan(1, 2, "name", 1L, Collections.<Long>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.<String>emptyList(), "spanId", true, true, "processId");
|
||||
MilliSpan span = new MilliSpan(1, 2, "name", 1L, Collections.<Long>emptyList(), 2L, true, true, "process");
|
||||
|
||||
span.logs().add(new Log(1, "1"));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<SpanAssert, Span> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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<String> traceIds = new ConcurrentLinkedQueue<>();
|
||||
Queue<String> spanIds = new ConcurrentLinkedQueue<>();
|
||||
Queue<Long> traceIds = new ConcurrentLinkedQueue<>();
|
||||
Queue<Long> spanIds = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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> T getValueFromHeaders(String headerName, Class<T> type) {
|
||||
return stompMessageHandler.message.getHeaders().get(headerName, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> span;
|
||||
AtomicReference<Span> 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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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<String> 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<String> response, String name) {
|
||||
|
||||
@@ -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.<ClientHttpRequestInterceptor>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<String, String> 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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<EmbeddedServletContainerInitializedEvent> {
|
||||
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<EmbeddedServletContainerInitializedEvent> {
|
||||
return new Callable<String>() {
|
||||
@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<EmbeddedServletContainerInitializedEvent> {
|
||||
@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<EmbeddedServletContainerInitializedEvent> {
|
||||
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<EmbeddedServletContainerInitializedEvent> {
|
||||
@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);
|
||||
|
||||
@@ -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<String> 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<String> 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<String> response = checkStateOfTheTraceId(traceId);
|
||||
log.info("Response from the Zipkin query service about the trace id [{}] for trace with id [{}]", response, traceId);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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<EmbeddedServletContainerInitializedEvent> {
|
||||
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<EmbeddedServletContainerInitializedEvent> {
|
||||
return new Callable<String>() {
|
||||
@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<EmbeddedServletContainerInitializedEvent> {
|
||||
@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<EmbeddedServletContainerInitializedEvent> {
|
||||
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<EmbeddedServletContainerInitializedEvent> {
|
||||
@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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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<EmbeddedServletContainerInitializedEvent> {
|
||||
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<EmbeddedServletContainerInitializedEvent> {
|
||||
return new Callable<String>() {
|
||||
@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<EmbeddedServletContainerInitializedEvent> {
|
||||
@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<EmbeddedServletContainerInitializedEvent> {
|
||||
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<EmbeddedServletContainerInitializedEvent> {
|
||||
@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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.<String>emptyList(), "spanId", true, true, "processId");
|
||||
MilliSpan span = new MilliSpan(1, 3, "name", 1L, Collections.<Long>emptyList(), 2L, true, true, "process");
|
||||
|
||||
@Test
|
||||
public void portDefaultsTo8080() {
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.<String>emptyList(), id, true, true, "proc");
|
||||
Long id = new Random().nextLong();
|
||||
return new MilliSpan(1, 3, name, id, Collections.<Long>emptyList(), id, true, true, "process");
|
||||
}
|
||||
}
|
||||
@@ -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.<String>emptyList(), "spanId", true, true, "processId");
|
||||
MilliSpan span = new MilliSpan(1, 3, "name", 1L, Collections.<Long>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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user