Add message keys to TraceKeys

User can now configure message headers to be added using
spring.sleuth.keys.message.headers.

Fixes gh-119

Also a bunch of cosmetic changes (imports etc).
This commit is contained in:
Dave Syer
2016-01-19 13:18:43 +00:00
parent af78160e52
commit da60403321
25 changed files with 229 additions and 183 deletions

View File

@@ -16,13 +16,13 @@
package org.springframework.cloud.sleuth.instrument;
import lombok.EqualsAndHashCode;
import lombok.Value;
import java.util.concurrent.Callable;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import java.util.concurrent.Callable;
import lombok.EqualsAndHashCode;
import lombok.Value;
/**
* @author Spencer Gibb

View File

@@ -54,6 +54,39 @@ public class TraceKeys {
private Http http = new Http();
private Message message = new Message();
@Data
public static class Message {
private Payload payload = new Payload();
@Data
public static class Payload {
/**
* An estimate of the size of the payload if available.
*/
private String size = "message/payload-size";
/**
* The type of the payload.
*/
private String type = "message/payload-type";
}
/**
* Prefix for header names if they are added as tags.
*/
private String prefix = "message/";
/**
* Additional headers that should be added as tags if they exist. If the header
* value is not a String it will be converted to a String using its toString()
* method.
*/
private Collection<String> headers = new LinkedHashSet<String>();
}
@Data
public static class Http {

View File

@@ -21,7 +21,6 @@ import org.springframework.cloud.sleuth.Tracer;
import lombok.EqualsAndHashCode;
import lombok.Value;
import org.springframework.cloud.sleuth.Tracer;
/**
* @author Spencer Gibb

View File

@@ -25,7 +25,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;

View File

@@ -24,7 +24,6 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceCallable;
import org.springframework.cloud.sleuth.instrument.TraceRunnable;

View File

@@ -21,7 +21,6 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceCallable;
import org.springframework.cloud.sleuth.instrument.TraceRunnable;

View File

@@ -1,17 +1,18 @@
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.Random;
import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.integration.channel.AbstractMessageChannel;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.ChannelInterceptorAdapter;
import java.util.Random;
/**
* Abstraction over classes related to channel intercepting
*
@@ -19,15 +20,26 @@ import java.util.Random;
*/
abstract class AbstractTraceChannelInterceptor extends ChannelInterceptorAdapter {
protected final Tracer tracer;
private final Tracer tracer;
protected final Random random;
private final Random random;
protected AbstractTraceChannelInterceptor(Tracer tracer, Random random) {
private final TraceKeys traceKeys;
protected AbstractTraceChannelInterceptor(Tracer tracer, TraceKeys traceKeys, Random random) {
this.tracer = tracer;
this.traceKeys = traceKeys;
this.random = random;
}
protected Tracer getTracer() {
return this.tracer;
}
protected TraceKeys getTraceKeys() {
return this.traceKeys;
}
/**
* Returns a span given the message and a channel. Returns null when there was no
* trace id passed initially.
@@ -37,7 +49,7 @@ abstract class AbstractTraceChannelInterceptor extends ChannelInterceptorAdapter
return null; // cannot build a span without ids
}
long spanId = hasHeader(message, Trace.SPAN_ID_NAME) ?
getHeader(message, Trace.SPAN_ID_NAME, Long.class) : random.nextLong();
getHeader(message, Trace.SPAN_ID_NAME, Long.class) : this.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);

View File

@@ -16,16 +16,17 @@
package org.springframework.cloud.sleuth.instrument.integration;
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;
import java.util.Map;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.util.StringUtils;
/**
* Utility for manipulating message headers related to span data.
*
@@ -34,7 +35,8 @@ import java.util.Map;
*/
public class SpanMessageHeaders {
public static Message<?> addSpanHeaders(Message<?> message, Span span) {
public static Message<?> addSpanHeaders(TraceKeys traceKeys, Message<?> message,
Span span) {
if (span == null) {
if (!message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) {
return MessageBuilder.fromMessage(message)
@@ -48,40 +50,42 @@ public class SpanMessageHeaders {
addHeader(headers, Trace.SPAN_ID_NAME, span.getSpanId());
if (span.isExportable()) {
addAnnotations(message, span);
addAnnotations(traceKeys, message, span);
addHeader(headers, Trace.PARENT_ID_NAME, getFirst(span.getParents()));
addHeader(headers, Trace.SPAN_NAME_NAME, span.getName());
addHeader(headers, Trace.PROCESS_ID_NAME, span.getProcessId());
} else {
}
else {
addHeader(headers, Trace.NOT_SAMPLED_NAME, "");
}
return MessageBuilder.fromMessage(message).copyHeaders(headers).build();
}
public static void addAnnotations(Message<?> message, Span span) {
for (Map.Entry<String, Object> entry : message.getHeaders().entrySet()) {
if (!Trace.HEADERS.contains(entry.getKey())) { // filter out trace headers
String key = "/messaging/headers/" + entry.getKey().toLowerCase();
String value = null;
if (entry.getValue() != null) {
value = entry.getValue().toString(); // TODO: better way to serialize?
public static void addAnnotations(TraceKeys traceKeys, Message<?> message,
Span span) {
for (String name : traceKeys.getMessage().getHeaders()) {
if (message.getHeaders().containsKey(name)) {
String key = traceKeys.getMessage().getPrefix() + name.toLowerCase();
Object value = message.getHeaders().get(name);
if (value == null) {
value = "null";
}
span.tag(key, value);
span.tag(key, value.toString()); // TODO: better way to serialize?
}
}
addPayloadAnnotations(message.getPayload(), span);
addPayloadAnnotations(traceKeys, message.getPayload(), span);
}
static void addPayloadAnnotations(Object payload, Span span) {
static void addPayloadAnnotations(TraceKeys traceKeys, Object payload, Span span) {
if (payload != null) {
span.tag("/messaging/payload/type",
span.tag(traceKeys.getMessage().getPayload().getType(),
payload.getClass().getCanonicalName());
if (payload instanceof String) {
span.tag("/messaging/payload/size",
span.tag(traceKeys.getMessage().getPayload().getSize(),
String.valueOf(((String) payload).length()));
}
else if (payload instanceof byte[]) {
span.tag("/messaging/payload/size",
span.tag(traceKeys.getMessage().getPayload().getSize(),
String.valueOf(((byte[]) payload).length));
}
}
@@ -94,8 +98,7 @@ public class SpanMessageHeaders {
}
}
private static void addHeader(Map<String, String> headers, String name,
Long value) {
private static void addHeader(Map<String, String> headers, String name, Long value) {
if (value != null) {
addHeader(headers, name, Span.IdConverter.toHex(value));
}

View File

@@ -16,6 +16,10 @@
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
@@ -24,18 +28,14 @@ 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;
import java.util.TreeMap;
/**
* Builder class to create STOMP message
*
*
* @author Gaurav Rai Mazra
*
*/
public class StompMessageBuilder {
public static StompMessageBuilder fromMessage(Message<?> message) {
return new StompMessageBuilder(message);
}
@@ -89,7 +89,7 @@ public class StompMessageBuilder {
headerAccessor.getMessageHeaders());
}
private void pushHeaders(final SimpMessageHeaderAccessor assessor, final String key, final Object value) {
private void pushHeaders(final SimpMessageHeaderAccessor accessor, final String key, final Object value) {
switch (key) {
case SimpMessageHeaderAccessor.DESTINATION_HEADER:
case SimpMessageHeaderAccessor.MESSAGE_TYPE_HEADER:
@@ -107,10 +107,10 @@ public class StompMessageBuilder {
case Trace.SPAN_ID_NAME:
case Trace.SPAN_NAME_NAME:
case Trace.TRACE_ID_NAME:
assessor.setHeader(key, value);
accessor.setHeader(key, value);
break;
default:
assessor.setNativeHeader(key, value == null ? null : value.toString());
accessor.setNativeHeader(key, value == null ? null : value.toString());
}
}

View File

@@ -16,15 +16,16 @@
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.Random;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.cloud.sleuth.sampler.IsTracingSampler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import java.util.Random;
/**
* @author Dave Syer
*
@@ -33,38 +34,38 @@ public class TraceChannelInterceptor extends AbstractTraceChannelInterceptor {
private ThreadLocal<Trace> traceHolder = new ThreadLocal<>();
public TraceChannelInterceptor(Tracer tracer, Random random) {
super(tracer, random);
public TraceChannelInterceptor(Tracer tracer, TraceKeys traceKeys, Random random) {
super(tracer, traceKeys, random);
}
@Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
Trace trace = this.traceHolder.get();
// Double close to clean up the parent (remote span as well)
this.tracer.close(this.tracer.close(trace));
getTracer().close(getTracer().close(trace));
this.traceHolder.remove();
}
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
if (this.tracer.isTracing()) {
return SpanMessageHeaders.addSpanHeaders(message,
this.tracer.getCurrentSpan());
if (getTracer().isTracing()) {
return SpanMessageHeaders.addSpanHeaders(getTraceKeys(), message,
getTracer().getCurrentSpan());
}
String name = getMessageChannelName(channel);
Trace trace = startSpan(buildSpan(message), name, message);
this.traceHolder.set(trace);
return SpanMessageHeaders.addSpanHeaders(message, trace.getSpan());
return SpanMessageHeaders.addSpanHeaders(getTraceKeys(), message, trace.getSpan());
}
private Trace startSpan(Span span, String name, Message message) {
private Trace startSpan(Span span, String name, Message<?> message) {
if (span != null) {
return tracer.joinTrace(name, span);
return getTracer().joinTrace(name, span);
}
if (message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) {
return tracer.startTrace(name, IsTracingSampler.INSTANCE);
return getTracer().startTrace(name, IsTracingSampler.INSTANCE);
}
return this.tracer.startTrace(name);
return getTracer().startTrace(name);
}
}

View File

@@ -16,19 +16,20 @@
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.Random;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
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
*/
@@ -37,6 +38,7 @@ import java.util.Random;
@ConditionalOnBean(Tracer.class)
@AutoConfigureAfter(TraceAutoConfiguration.class)
@ConditionalOnProperty(value = "spring.sleuth.integration.enabled", matchIfMissing = true)
@EnableConfigurationProperties(TraceKeys.class)
public class TraceSpringIntegrationAutoConfiguration {
@Bean
@@ -48,19 +50,21 @@ public class TraceSpringIntegrationAutoConfiguration {
@Bean
@GlobalChannelInterceptor
public TraceChannelInterceptor traceChannelInterceptor(Tracer tracer, Random random) {
return new TraceChannelInterceptor(tracer, random);
public TraceChannelInterceptor traceChannelInterceptor(Tracer tracer,
TraceKeys traceKeys, Random random) {
return new TraceChannelInterceptor(tracer, traceKeys, random);
}
@Bean
public TraceStompMessageChannelInterceptor traceStompMessageChannelInterceptor(Tracer tracer, Random random) {
return new TraceStompMessageChannelInterceptor(tracer, random);
public TraceStompMessageChannelInterceptor traceStompMessageChannelInterceptor(
Tracer tracer, TraceKeys traceKeys, Random random) {
return new TraceStompMessageChannelInterceptor(tracer, traceKeys, random);
}
@Bean
public TraceStompMessageContextPropagationChannelInterceptor traceStompMessageContextPropagationChannelInteceptor(
Tracer tracer) {
return new TraceStompMessageContextPropagationChannelInterceptor(tracer);
Tracer tracer, TraceKeys traceKeys) {
return new TraceStompMessageContextPropagationChannelInterceptor(tracer, traceKeys);
}
}

View File

@@ -15,33 +15,34 @@
*/
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.Random;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
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
*
*
* @author Gaurav Rai Mazra
* @author Marcin Grzejszczak
*
*
*/
public class TraceStompMessageChannelInterceptor extends AbstractTraceChannelInterceptor implements ChannelInterceptor {
private ThreadLocal<Trace> traceScopeHolder = new ThreadLocal<Trace>();
public TraceStompMessageChannelInterceptor(Tracer tracer, Random random) {
super(tracer, random);
public TraceStompMessageChannelInterceptor(Tracer tracer, TraceKeys traceKeys, Random random) {
super(tracer, traceKeys, random);
}
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
if (tracer.isTracing() || message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) {
return StompMessageBuilder.fromMessage(message).setHeadersFromSpan(tracer.getCurrentSpan()).build();
if (getTracer().isTracing() || message.getHeaders().containsKey(Trace.NOT_SAMPLED_NAME)) {
return StompMessageBuilder.fromMessage(message).setHeadersFromSpan(getTracer().getCurrentSpan()).build();
}
String name = getMessageChannelName(channel);
Trace trace = startSpan(buildSpan(message), name);
@@ -51,16 +52,16 @@ public class TraceStompMessageChannelInterceptor extends AbstractTraceChannelInt
private Trace startSpan(Span span, String name) {
if (span != null) {
return tracer.joinTrace(name, span);
return getTracer().joinTrace(name, span);
}
return tracer.startTrace(name);
return getTracer().startTrace(name);
}
@Override
public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
final ThreadLocal<Trace> traceScopeHolder = this.traceScopeHolder;
Trace traceInScope = traceScopeHolder.get();
this.tracer.close(traceInScope);
getTracer().close(traceInScope);
traceScopeHolder.remove();
}
}

View File

@@ -16,13 +16,11 @@
package org.springframework.cloud.sleuth.instrument.integration;
import java.util.Map;
import org.springframework.aop.support.AopUtils;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceKeys;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
@@ -43,9 +41,11 @@ public class TraceStompMessageContextPropagationChannelInterceptor extends Chann
private final Tracer tracer;
private final static ThreadLocal<Trace> ORIGINAL_CONTEXT = new ThreadLocal<>();
private TraceKeys traceKeys;
public TraceStompMessageContextPropagationChannelInterceptor(Tracer tracer) {
public TraceStompMessageContextPropagationChannelInterceptor(Tracer tracer, TraceKeys traceKeys) {
this.tracer = tracer;
this.traceKeys = traceKeys;
}
@Override
@@ -55,12 +55,23 @@ public class TraceStompMessageContextPropagationChannelInterceptor extends Chann
}
Span span = this.tracer.getCurrentSpan();
if (span != null) {
return new MessageWithSpan(message, span);
return createMessageWithSpan(message, span);
} else {
return message;
}
}
private Message<?> createMessageWithSpan(Message<?> message, Span span) {
MessageWithSpan output = new MessageWithSpan(message, span);
addAnnotationsToSpanFromMessage(output, span);
return output;
}
private void addAnnotationsToSpanFromMessage(Message<?> message, Span span) {
SpanMessageHeaders.addAnnotations(this.traceKeys, message, span);
SpanMessageHeaders.addPayloadAnnotations(this.traceKeys, message.getPayload(), span);
}
@Override
public final Message<?> postReceive(Message<?> message, MessageChannel channel) {
if (message instanceof MessageWithSpan) {
@@ -103,18 +114,6 @@ public class TraceStompMessageContextPropagationChannelInterceptor extends Chann
Assert.notNull(span, "span can not be null");
this.span = span;
this.message = StompMessageBuilder.fromMessage(message).setHeadersFromSpan(this.span).build();
addAnnotationsToSpanFromMessage(this.message, this.span);
}
private void addAnnotationsToSpanFromMessage(Message<?> message, Span span) {
for (Map.Entry<String, Object> entry : message.getHeaders().entrySet()) {
if (!Trace.HEADERS.contains(entry.getKey())) {
String key = "/messaging/headers/" + entry.getKey().toLowerCase();
String value = entry.getValue() == null ? null : entry.getValue().toString();
span.tag(key, value);
}
}
SpanMessageHeaders.addPayloadAnnotations(message.getPayload(), span);
}
@Override

View File

@@ -26,7 +26,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@@ -25,7 +25,6 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.cloud.sleuth.TraceAccessor;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceCallable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;

View File

@@ -21,7 +21,6 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.hystrix.TraceCommand;
@@ -38,11 +37,11 @@ import feign.Target;
*/
final class SleuthHystrixInvocationHandler implements InvocationHandler {
private final Target target;
private final Target<?> target;
private final Map<Method, MethodHandler> dispatch;
private final Tracer tracer;
SleuthHystrixInvocationHandler(Target target, Map<Method, MethodHandler> dispatch, Tracer tracer) {
SleuthHystrixInvocationHandler(Target<?> target, Map<Method, MethodHandler> dispatch, Tracer tracer) {
this.tracer = checkNotNull(tracer, "traceManager");
this.target = checkNotNull(target, "target");
this.dispatch = checkNotNull(dispatch, "dispatch");
@@ -56,7 +55,7 @@ final class SleuthHystrixInvocationHandler implements InvocationHandler {
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey));
HystrixCommand<Object> hystrixCommand = new TraceCommand<Object>(tracer, setter) {
HystrixCommand<Object> hystrixCommand = new TraceCommand<Object>(this.tracer, setter) {
@Override
public Object doRun() throws Exception {
try {
@@ -84,8 +83,8 @@ final class SleuthHystrixInvocationHandler implements InvocationHandler {
}
@Override
public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
return new SleuthHystrixInvocationHandler(target, dispatch, tracer);
public InvocationHandler create(@SuppressWarnings("rawtypes") Target target, Map<Method, MethodHandler> dispatch) {
return new SleuthHystrixInvocationHandler(target, dispatch, this.tracer);
}
}
}

View File

@@ -16,10 +16,14 @@
package org.springframework.cloud.sleuth.instrument.web.client;
import com.netflix.hystrix.HystrixCommand;
import feign.*;
import feign.codec.Decoder;
import feign.hystrix.HystrixFeign;
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 org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -35,7 +39,6 @@ import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.TraceAccessor;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixAutoConfiguration;
@@ -48,13 +51,16 @@ import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.util.StringUtils;
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 static java.util.Collections.singletonList;
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;
/**
*

View File

@@ -23,7 +23,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@@ -1,6 +1,5 @@
package org.springframework.cloud.sleuth.sampler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.TraceAccessor;
@@ -21,7 +20,6 @@ import org.springframework.cloud.sleuth.TraceAccessor;
* @author Marcin Grzejszczak
* @author Adrian Cole
*/
@Slf4j
public class PercentageBasedSampler implements Sampler<Void> {
private final SamplerConfiguration configuration;
@@ -34,8 +32,8 @@ public class PercentageBasedSampler implements Sampler<Void> {
@Override
public boolean next() {
Span currentSpan = traceAccessor.getCurrentSpan();
long threshold = Math.abs(Long.MAX_VALUE * (int) (configuration.getPercentage() * 100)); // drops fractional percentage.
Span currentSpan = this.traceAccessor.getCurrentSpan();
long threshold = Math.abs(Long.MAX_VALUE * (int) (this.configuration.getPercentage() * 100)); // drops fractional percentage.
if (currentSpan == null || threshold == 0L) {
return false;
}

View File

@@ -18,7 +18,6 @@ package org.springframework.cloud.sleuth.template;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.TraceDelegate;
/**

View File

@@ -1,5 +1,11 @@
package org.springframework.cloud.sleuth.instrument;
import static org.assertj.core.api.BDDAssertions.then;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -7,19 +13,11 @@ import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.context.ApplicationEventPublisher;
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 {

View File

@@ -1,6 +1,17 @@
package org.springframework.cloud.sleuth.instrument.executor;
import lombok.SneakyThrows;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.BDDAssertions.then;
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;
import java.util.concurrent.Executors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -15,17 +26,7 @@ import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.context.ApplicationEventPublisher;
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;
import java.util.concurrent.Executors;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.BDDAssertions.then;
import lombok.SneakyThrows;
@RunWith(MockitoJUnitRunner.class)
public class TraceableExecutorServiceTests {
@@ -39,34 +40,34 @@ public class TraceableExecutorServiceTests {
@Before
public void setup() {
tracer = new DefaultTracer(new AlwaysSampler(), new Random(), publisher);
traceManagerableExecutorService = new TraceableExecutorService(executorService, tracer);
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher);
this.traceManagerableExecutorService = new TraceableExecutorService(this.executorService, this.tracer);
TraceContextHolder.removeCurrentTrace();
}
@After
public void tearDown() throws Exception {
tracer = null;
traceManagerableExecutorService.shutdown();
executorService.shutdown();
this.tracer = null;
this.traceManagerableExecutorService.shutdown();
this.executorService.shutdown();
TraceContextHolder.removeCurrentTrace();
}
@Test
@SneakyThrows
public void should_propagate_trace_id_and_set_new_span_when_traceable_executor_service_is_executed() {
Trace trace = tracer.startTrace("PARENT");
Trace trace = this.tracer.startTrace("PARENT");
CompletableFuture.allOf(runnablesExecutedViaTraceManagerableExecutorService()).get();
tracer.close(trace);
this.tracer.close(trace);
then(spanVerifyingRunnable.traceIds.stream().distinct().collect(toList())).containsOnly(trace.getSpan().getTraceId());
then(spanVerifyingRunnable.spanIds.stream().distinct().collect(toList())).hasSize(TOTAL_THREADS);
then(this.spanVerifyingRunnable.traceIds.stream().distinct().collect(toList())).containsOnly(trace.getSpan().getTraceId());
then(this.spanVerifyingRunnable.spanIds.stream().distinct().collect(toList())).hasSize(TOTAL_THREADS);
}
private CompletableFuture[] runnablesExecutedViaTraceManagerableExecutorService() {
List<CompletableFuture> futures = new ArrayList<>();
private CompletableFuture<?>[] runnablesExecutedViaTraceManagerableExecutorService() {
List<CompletableFuture<?>> futures = new ArrayList<>();
for (int i = 0; i < TOTAL_THREADS; i++) {
futures.add(CompletableFuture.runAsync(spanVerifyingRunnable, traceManagerableExecutorService));
futures.add(CompletableFuture.runAsync(this.spanVerifyingRunnable, this.traceManagerableExecutorService));
}
return futures.toArray(new CompletableFuture[futures.size()]);
}
@@ -79,8 +80,8 @@ public class TraceableExecutorServiceTests {
@Override
public void run() {
Span span = TraceContextHolder.getCurrentSpan();
traceIds.add(span.getTraceId());
spanIds.add(span.getSpanId());
this.traceIds.add(span.getTraceId());
this.spanIds.add(span.getSpanId());
}
}

View File

@@ -1,5 +1,7 @@
package org.springframework.cloud.sleuth.instrument.integration;
import static org.assertj.core.api.BDDAssertions.then;
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
@@ -14,10 +16,8 @@ import org.springframework.messaging.support.ExecutorSubscribableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringJUnit4ClassRunner.class)
abstract class AbstractTraceStompIntegrationTests {
public abstract class AbstractTraceStompIntegrationTests {
@Autowired
@Qualifier("executorSubscribableChannel")
@@ -29,17 +29,17 @@ abstract class AbstractTraceStompIntegrationTests {
@Before
public void init() {
this.channel.subscribe(stompMessageHandler);
this.channel.subscribe(this.stompMessageHandler);
}
@After
public void close() {
TraceContextHolder.removeCurrentTrace();
this.channel.unsubscribe(stompMessageHandler);
this.channel.unsubscribe(this.stompMessageHandler);
}
Trace givenALocallyStartedSpan() {
return tracer.startTrace("testSendMessage", sampler);
return this.tracer.startTrace("testSendMessage", this.sampler);
}
Message<?> givenMessageToBeSampled() {
@@ -48,7 +48,7 @@ abstract class AbstractTraceStompIntegrationTests {
void whenTheMessageWasSent(Message<?> message) {
this.channel.send(message);
then(stompMessageHandler.message).isNotNull();
then(this.stompMessageHandler.message).isNotNull();
}
Long thenSpanIdFromHeadersIsNotEmpty() {
@@ -64,6 +64,6 @@ abstract class AbstractTraceStompIntegrationTests {
}
<T> T getValueFromHeaders(String headerName, Class<T> type) {
return stompMessageHandler.message.getHeaders().get(headerName, type);
return this.stompMessageHandler.message.getHeaders().get(headerName, type);
}
}

View File

@@ -1,8 +1,12 @@
package org.springframework.cloud.sleuth.instrument.web.client;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import static org.assertj.core.api.BDDAssertions.then;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -18,7 +22,6 @@ import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
@@ -35,12 +38,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import static org.assertj.core.api.BDDAssertions.then;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { FeignTraceTests.TestConfiguration.class })

View File

@@ -16,6 +16,14 @@
package org.springframework.cloud.sleuth.instrument.web.client;
import static org.assertj.core.api.BDDAssertions.then;
import static org.junit.Assert.assertFalse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -23,7 +31,6 @@ import org.springframework.cloud.sleuth.MilliSpan;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TraceContextHolder;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.http.HttpHeaders;
@@ -36,14 +43,6 @@ 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
*