diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java
index faf5c64a8..fd79562a7 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/Span.java
@@ -27,13 +27,13 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
/**
* Class for gathering and reporting statistics about a block of execution.
*
@@ -377,7 +377,11 @@ public class Span {
@Override
public String toString() {
return "[Trace: " + idToHex(this.traceId) + ", Span: " + idToHex(this.spanId)
- + ", exportable=" + this.exportable + "]";
+ + ", Parent: " + getParentIdIfPresent() + ", exportable=" + this.exportable + "]";
+ }
+
+ private String getParentIdIfPresent() {
+ return this.getParents().isEmpty() ? "null" : idToHex(this.getParents().get(0));
}
@Override
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHook.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHook.java
index bf8061a33..04cf31788 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHook.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/rxjava/SleuthRxJavaSchedulersHook.java
@@ -56,12 +56,14 @@ class SleuthRxJavaSchedulersHook extends RxJavaSchedulersHook {
private void logCurrentStateOfRxJavaPlugins(RxJavaErrorHandler errorHandler,
RxJavaObservableExecutionHook observableExecutionHook) {
- log.debug("Current RxJava plugins configuration is ["
- + "schedulersHook [" + this.delegate + "],"
- + "errorHandler [" + errorHandler + "],"
- + "observableExecutionHook [" + observableExecutionHook + "],"
- + "]");
- log.debug("Registering Sleuth RxJava Schedulers Hook.");
+ if (log.isDebugEnabled()) {
+ log.debug("Current RxJava plugins configuration is ["
+ + "schedulersHook [" + this.delegate + "],"
+ + "errorHandler [" + errorHandler + "],"
+ + "observableExecutionHook [" + observableExecutionHook + "],"
+ + "]");
+ log.debug("Registering Sleuth RxJava Schedulers Hook.");
+ }
}
@Override
@@ -102,9 +104,11 @@ class SleuthRxJavaSchedulersHook extends RxJavaSchedulersHook {
for (String threadToIgnore : this.threadsToIgnore) {
String threadName = Thread.currentThread().getName();
if (threadName.matches(threadToIgnore)) {
- log.trace(String.format(
- "Thread with name [%s] matches the regex [%s]. A span will not be created for this Thread.",
- threadName, threadToIgnore));
+ if (log.isTraceEnabled()) {
+ log.trace(String.format(
+ "Thread with name [%s] matches the regex [%s]. A span will not be created for this Thread.",
+ threadName, threadToIgnore));
+ }
this.actual.call();
return;
}
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/HttpTraceKeysInjector.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/HttpTraceKeysInjector.java
index 0d9a1b4f1..7fd87dfba 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/HttpTraceKeysInjector.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/HttpTraceKeysInjector.java
@@ -1,5 +1,6 @@
package org.springframework.cloud.sleuth.instrument.web;
+import java.net.URI;
import java.util.Collection;
import java.util.Map;
@@ -45,6 +46,13 @@ public class HttpTraceKeysInjector {
tagSpan(span, this.traceKeys.getHttp().getMethod(), method);
}
+ /**
+ * Adds tags from the HTTP request to the given Span
+ */
+ public void addRequestTags(Span span, URI uri, String method) {
+ addRequestTags(span, uri.toString(), uri.getHost(), uri.getPath(), method);
+ }
+
/**
* Adds tags from the HTTP request together with headers to the current Span
*/
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java
index 5b0f2b72c..20ef24468 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java
@@ -17,14 +17,19 @@ package org.springframework.cloud.sleuth.instrument.web;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.regex.Pattern;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanExtractor;
import org.springframework.cloud.sleuth.SpanInjector;
@@ -36,7 +41,8 @@ import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
-import org.springframework.web.filter.OncePerRequestFilter;
+import org.springframework.web.context.request.async.WebAsyncUtils;
+import org.springframework.web.filter.GenericFilterBean;
import org.springframework.web.util.UrlPathHelper;
import static org.springframework.util.StringUtils.hasText;
@@ -63,13 +69,18 @@ import static org.springframework.util.StringUtils.hasText;
* @see TraceWebAutoConfiguration#traceFilter
*/
@Order(Ordered.HIGHEST_PRECEDENCE + 5)
-public class TraceFilter extends OncePerRequestFilter {
+public class TraceFilter extends GenericFilterBean {
+
+ private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
private static final String HTTP_COMPONENT = "http";
protected static final String TRACE_REQUEST_ATTR = TraceFilter.class.getName()
+ ".TRACE";
+ protected static final String TRACE_ERROR_HANDLED_REQUEST_ATTR = TraceFilter.class.getName()
+ + ".ERROR_HANDLED";
+
public static final String DEFAULT_SKIP_PATTERN =
"/api-docs.*|/autoconfig|/configprops|/dump|/health|/info|/metrics.*|/mappings|/trace|/swagger.*|.*\\.png|.*\\.css|.*\\.js|.*\\.html|/favicon.ico|/hystrix.stream";
@@ -105,22 +116,36 @@ public class TraceFilter extends OncePerRequestFilter {
}
@Override
- protected void doFilterInternal(HttpServletRequest request,
- HttpServletResponse response, FilterChain filterChain)
- throws ServletException, IOException {
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
+ FilterChain filterChain) throws IOException, ServletException {
+ if (!(servletRequest instanceof HttpServletRequest) || !(servletResponse instanceof HttpServletResponse)) {
+ throw new ServletException("Filter just supports HTTP requests");
+ }
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ HttpServletResponse response = (HttpServletResponse) servletResponse;
String uri = this.urlPathHelper.getPathWithinApplication(request);
boolean skip = this.skipPattern.matcher(uri).matches()
|| Span.SPAN_NOT_SAMPLED.equals(ServletUtils.getHeader(request, response, Span.SAMPLED_NAME));
Span spanFromRequest = getSpanFromAttribute(request);
if (spanFromRequest != null) {
this.tracer.continueSpan(spanFromRequest);
+ if (log.isTraceEnabled()) {
+ log.trace("There has already been a span in the request " + spanFromRequest + "");
+ }
+ }
+ if (log.isTraceEnabled()) {
+ log.trace("Received a request to uri [" + uri + "] that matches the skip pattern [" + skip + "]");
}
// in case of a response with exception status a exception controller will close the span
if (!httpStatusSuccessful(response) && isSpanContinued(request)) {
- // it means that the span was already detached once and we're processing an error
+ if (log.isTraceEnabled()) {
+ log.trace(
+ "The span was already detached once and we're processing an error");
+ }
try {
filterChain.doFilter(request, response);
} finally {
+ request.setAttribute(TRACE_ERROR_HANDLED_REQUEST_ATTR, true);
this.tracer.close(spanFromRequest);
}
return;
@@ -141,6 +166,9 @@ public class TraceFilter extends OncePerRequestFilter {
}
finally {
if (isAsyncStarted(request) || request.isAsyncStarted()) {
+ if (log.isTraceEnabled()) {
+ log.trace("Detaching the span " + spanFromRequest + " since the request is asynchronous");
+ }
this.tracer.detach(spanFromRequest);
// TODO: how to deal with response annotations and async?
return;
@@ -151,6 +179,9 @@ public class TraceFilter extends OncePerRequestFilter {
if (spanFromRequest.hasSavedSpan()) {
Span parent = spanFromRequest.getSavedSpan();
if (parent.isRemote()) {
+ if (log.isTraceEnabled()) {
+ log.trace("Sending the parent span " + parent + " to Zipkin");
+ }
parent.logEvent(Span.SERVER_SEND);
parent.stop();
this.spanReporter.report(parent);
@@ -160,8 +191,19 @@ public class TraceFilter extends OncePerRequestFilter {
}
// in case of a response with exception status will close the span when exception dispatch is handled
if (httpStatusSuccessful(response)) {
+ if (log.isTraceEnabled()) {
+ log.trace("Closing the span " + spanFromRequest + " since the response was successful");
+ }
this.tracer.close(spanFromRequest);
+ } else if (errorAlreadyHandled(request)) {
+ if (log.isTraceEnabled()) {
+ log.trace(
+ "Won't detach the span since error has already been handled");
+ }
} else {
+ if (log.isTraceEnabled()) {
+ log.trace("Detaching the span " + spanFromRequest + " since the response was unsuccessful");
+ }
this.tracer.detach(spanFromRequest);
}
}
@@ -177,6 +219,11 @@ public class TraceFilter extends OncePerRequestFilter {
return (Span) request.getAttribute(TRACE_REQUEST_ATTR);
}
+ private boolean errorAlreadyHandled(HttpServletRequest request) {
+ return Boolean.valueOf(
+ String.valueOf(request.getAttribute(TRACE_ERROR_HANDLED_REQUEST_ATTR)));
+ }
+
private boolean isSpanContinued(HttpServletRequest request) {
return getSpanFromAttribute(request) != null;
}
@@ -193,16 +240,28 @@ public class TraceFilter extends OncePerRequestFilter {
private Span createSpan(HttpServletRequest request,
boolean skip, Span spanFromRequest, String name) {
if (spanFromRequest != null) {
+ if (log.isTraceEnabled()) {
+ log.trace("Span has already been created - continuing with the previous one");
+ }
return spanFromRequest;
}
Span parent = this.spanExtractor.joinTrace(request);
if (parent != null) {
+ if (log.isTraceEnabled()) {
+ log.trace("Found a parent span " + parent + " in the request");
+ }
addRequestTagsForParentSpan(request, parent);
spanFromRequest = this.tracer.createSpan(name, parent);
+ if (log.isTraceEnabled()) {
+ log.trace("Started a new span " + spanFromRequest + " with parent " + parent);
+ }
if (parent.isRemote()) {
parent.logEvent(Span.SERVER_RECV);
}
request.setAttribute(TRACE_REQUEST_ATTR, spanFromRequest);
+ if (log.isTraceEnabled()) {
+ log.trace("Parent span is " + parent + "");
+ }
}
else {
if (skip) {
@@ -213,6 +272,7 @@ public class TraceFilter extends OncePerRequestFilter {
}
spanFromRequest.logEvent(Span.SERVER_RECV);
request.setAttribute(TRACE_REQUEST_ATTR, spanFromRequest);
+ log.trace("No parent span present - creating a new span");
}
return spanFromRequest;
}
@@ -256,9 +316,8 @@ public class TraceFilter extends OncePerRequestFilter {
}
}
- @Override
- protected boolean shouldNotFilterAsyncDispatch() {
- return false;
+ protected boolean isAsyncStarted(HttpServletRequest request) {
+ return WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted();
}
private String getFullUrl(HttpServletRequest request) {
@@ -266,14 +325,8 @@ public class TraceFilter extends OncePerRequestFilter {
String queryString = request.getQueryString();
if (queryString == null) {
return requestURI.toString();
- }
- else {
+ } else {
return requestURI.append('?').append(queryString).toString();
}
}
-
- @Override
- protected boolean shouldNotFilterErrorDispatch() {
- return false;
- }
}
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/AbstractTraceHttpRequestInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/AbstractTraceHttpRequestInterceptor.java
index 7c5e7e960..2abc5a033 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/AbstractTraceHttpRequestInterceptor.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/AbstractTraceHttpRequestInterceptor.java
@@ -16,8 +16,11 @@
package org.springframework.cloud.sleuth.instrument.web.client;
+import java.lang.invoke.MethodHandles;
import java.net.URI;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanInjector;
import org.springframework.cloud.sleuth.Tracer;
@@ -32,6 +35,8 @@ import org.springframework.http.HttpRequest;
*/
abstract class AbstractTraceHttpRequestInterceptor {
+ protected static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
+
protected final Tracer tracer;
protected final SpanInjector spanInjector;
protected final HttpTraceKeysInjector keysInjector;
@@ -54,6 +59,9 @@ abstract class AbstractTraceHttpRequestInterceptor {
this.spanInjector.inject(newSpan, request);
addRequestTags(request);
newSpan.logEvent(Span.CLIENT_SEND);
+ if (log.isTraceEnabled()) {
+ log.trace("Starting new client span [" + newSpan + "]");
+ }
}
private String uriScheme(URI uri) {
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java
index 2c07340b0..93ee4f98a 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceRestTemplateInterceptor.java
@@ -56,6 +56,9 @@ public class TraceRestTemplateInterceptor extends AbstractTraceHttpRequestInterc
try {
return new TraceHttpResponse(this, execution.execute(request, body));
} catch (Exception e) {
+ if (log.isTraceEnabled()) {
+ log.trace("Exception occurred while trying to execute the request", e);
+ }
this.tracer.close(currentSpan());
throw e;
}
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilter.java
index 79863acdd..ff32b5a44 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilter.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePostZuulFilter.java
@@ -16,12 +16,16 @@
package org.springframework.cloud.sleuth.instrument.zuul;
-import org.springframework.cloud.sleuth.Span;
-import org.springframework.cloud.sleuth.Tracer;
+import java.lang.invoke.MethodHandles;
import com.netflix.zuul.ZuulFilter;
-/**
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.cloud.sleuth.Span;
+import org.springframework.cloud.sleuth.Tracer;
+
+/**8
* A post request {@link ZuulFilter} that publishes an event upon start of the filtering
*
* @author Dave Syer
@@ -29,6 +33,8 @@ import com.netflix.zuul.ZuulFilter;
*/
public class TracePostZuulFilter extends ZuulFilter {
+ private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
+
private final Tracer tracer;
public TracePostZuulFilter(Tracer tracer) {
@@ -44,6 +50,9 @@ public class TracePostZuulFilter extends ZuulFilter {
public Object run() {
// TODO: the client sent event should come from the client not the filter!
getCurrentSpan().logEvent(Span.CLIENT_RECV);
+ if (log.isTraceEnabled()) {
+ log.trace("Closing current client span " + getCurrentSpan() + "");
+ }
this.tracer.close(getCurrentSpan());
return null;
}
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilter.java
index 802b4d7e7..090fd10c7 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilter.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TracePreZuulFilter.java
@@ -16,15 +16,19 @@
package org.springframework.cloud.sleuth.instrument.zuul;
-import org.springframework.cloud.sleuth.Span;
-import org.springframework.cloud.sleuth.SpanInjector;
-import org.springframework.cloud.sleuth.Tracer;
+import java.lang.invoke.MethodHandles;
import com.netflix.zuul.ExecutionStatus;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.ZuulFilterResult;
import com.netflix.zuul.context.RequestContext;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.cloud.sleuth.Span;
+import org.springframework.cloud.sleuth.SpanInjector;
+import org.springframework.cloud.sleuth.Tracer;
+
/**
* A pre request {@link ZuulFilter} that sets tracing related headers on the request
* from the current span. We're doing so to ensure tracing propagates to the next hop.
@@ -34,6 +38,8 @@ import com.netflix.zuul.context.RequestContext;
*/
public class TracePreZuulFilter extends ZuulFilter {
+ private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
+
private static final String ZUUL_COMPONENT = "zuul";
private final Tracer tracer;
@@ -59,11 +65,24 @@ public class TracePreZuulFilter extends ZuulFilter {
public ZuulFilterResult runFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
Span span = getCurrentSpan();
+ if (log.isTraceEnabled()) {
+ log.trace("Current span is " + span + "");
+ }
Span newSpan = this.tracer.createSpan(span.getName(), span);
newSpan.tag(Span.SPAN_LOCAL_COMPONENT_TAG_NAME, ZUUL_COMPONENT);
this.spanInjector.inject(newSpan, ctx);
+ if (log.isTraceEnabled()) {
+ log.trace("New Zuul Span is " + newSpan + "");
+ }
ZuulFilterResult result = super.runFilter();
+ if (log.isTraceEnabled()) {
+ log.trace("Result of Zuul filter is [" + result.getStatus() + "]");
+ }
if (ExecutionStatus.SUCCESS != result.getStatus()) {
+ if (log.isTraceEnabled()) {
+ log.trace("The result of Zuul filter execution was not successful thus "
+ + "will close the current span " + newSpan);
+ }
this.tracer.close(newSpan);
}
return result;
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactory.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactory.java
index 55215ab65..dafdcd4e6 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactory.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactory.java
@@ -19,6 +19,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 org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
@@ -28,11 +31,9 @@ import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanInjector;
import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.instrument.web.HttpTraceKeysInjector;
import org.springframework.util.MultiValueMap;
-import com.netflix.client.http.HttpRequest;
-import com.netflix.niws.client.http.RestClient;
-
/**
* Propagates traces downstream via http headers that contain trace metadata.
*
@@ -45,12 +46,15 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
private final Tracer tracer;
private final SpanInjector spanInjector;
+ private final HttpTraceKeysInjector httpTraceKeysInjector;
public TraceRestClientRibbonCommandFactory(SpringClientFactory clientFactory,
- Tracer tracer, SpanInjector spanInjector) {
+ Tracer tracer, SpanInjector spanInjector,
+ HttpTraceKeysInjector httpTraceKeysInjector) {
super(clientFactory);
this.tracer = tracer;
this.spanInjector = spanInjector;
+ this.httpTraceKeysInjector = httpTraceKeysInjector;
}
@Override
@@ -62,7 +66,7 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
return new TraceRestClientRibbonCommand(context.getServiceId(), restClient,
getVerb(context.getVerb()), context.getUri(), context.getRetryable(),
context.getHeaders(), context.getParams(), context.getRequestEntity(),
- this.tracer, this.spanInjector);
+ this.tracer, this.spanInjector, this.httpTraceKeysInjector);
}
catch (URISyntaxException e) {
log.error("Exception occurred while trying to create the TraceRestClientRibbonCommand", e);
@@ -74,25 +78,32 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
private final Tracer tracer;
private final SpanInjector spanInjector;
+ private final HttpTraceKeysInjector httpTraceKeysInjector;
@SuppressWarnings("deprecation")
public TraceRestClientRibbonCommand(String commandKey, RestClient restClient,
HttpRequest.Verb verb, String uri, Boolean retryable,
MultiValueMap headers,
MultiValueMap params, InputStream requestEntity,
- Tracer tracer, SpanInjector spanInjector)
+ Tracer tracer, SpanInjector spanInjector,
+ HttpTraceKeysInjector httpTraceKeysInjector)
throws URISyntaxException {
super(commandKey, restClient, verb, uri, retryable, headers, params,
requestEntity);
this.tracer = tracer;
this.spanInjector = spanInjector;
+ this.httpTraceKeysInjector = httpTraceKeysInjector;
}
@Override
protected void customizeRequest(HttpRequest.Builder requestBuilder) {
Span span = getCurrentSpan();
this.spanInjector.inject(span, requestBuilder);
+ this.httpTraceKeysInjector.addRequestTags(span, getUri(), getVerb().verb());
span.logEvent(Span.CLIENT_SEND);
+ if (log.isTraceEnabled()) {
+ log.trace("Span is " + span);
+ }
}
private Span getCurrentSpan() {
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java
index f9cc68514..eaedb0fa0 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulAutoConfiguration.java
@@ -25,6 +25,7 @@ import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.sleuth.SpanInjector;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
+import org.springframework.cloud.sleuth.instrument.web.HttpTraceKeysInjector;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -56,8 +57,9 @@ public class TraceZuulAutoConfiguration {
@Bean
public TraceRestClientRibbonCommandFactory traceRestClientRibbonCommandFactory(SpringClientFactory factory,
- Tracer tracer, SpanInjector spanInjector) {
- return new TraceRestClientRibbonCommandFactory(factory, tracer, spanInjector);
+ Tracer tracer, SpanInjector spanInjector, HttpTraceKeysInjector httpTraceKeysInjector) {
+ return new TraceRestClientRibbonCommandFactory(factory, tracer, spanInjector,
+ httpTraceKeysInjector);
}
@Bean
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanLogger.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanLogger.java
index 29c2f03e3..3df9f1b03 100644
--- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanLogger.java
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanLogger.java
@@ -83,7 +83,9 @@ public class Slf4jSpanLogger implements SpanLogger {
if (span != null && this.nameSkipPattern.matcher(span.getName()).matches()) {
return;
}
- this.log.trace(text, span);
+ if (this.log.isTraceEnabled()) {
+ this.log.trace(text, span);
+ }
}
}
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTests.java
similarity index 99%
rename from spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java
rename to spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTests.java
index 910910a55..7a09ae389 100644
--- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTest.java
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/SpanTests.java
@@ -19,11 +19,11 @@ package org.springframework.cloud.sleuth;
import java.io.IOException;
import java.util.Collections;
-import org.junit.Test;
-
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+
import static org.assertj.core.api.BDDAssertions.then;
/**
@@ -31,7 +31,7 @@ import static org.assertj.core.api.BDDAssertions.then;
* @author Rob Winch
* @author Spencer Gibb
*/
-public class SpanTest {
+public class SpanTests {
@Test
public void should_convert_long_to_hex_string() throws Exception {
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/ListOfSpans.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/ListOfSpans.java
new file mode 100644
index 000000000..697a2b079
--- /dev/null
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/ListOfSpans.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.cloud.sleuth.assertions;
+
+import java.util.List;
+
+import org.springframework.cloud.sleuth.Span;
+
+/**
+ * @author Marcin Grzejszczak
+ */
+public class ListOfSpans {
+
+ public final List spans;
+
+ public ListOfSpans(List spans) {
+ this.spans = spans;
+ }
+}
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/ListOfSpansAssert.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/ListOfSpansAssert.java
new file mode 100644
index 000000000..6172561ef
--- /dev/null
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/ListOfSpansAssert.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2013-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.cloud.sleuth.assertions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.assertj.core.api.AbstractAssert;
+import org.assertj.core.api.Assertions;
+import org.springframework.cloud.sleuth.Span;
+
+public class ListOfSpansAssert extends AbstractAssert {
+
+ private static final Log log = LogFactory.getLog(ListOfSpansAssert.class);
+
+ private final ObjectMapper objectMapper = new ObjectMapper();
+
+ public ListOfSpansAssert(ListOfSpans actual) {
+ super(actual, ListOfSpansAssert.class);
+ }
+
+ public static ListOfSpansAssert then(ListOfSpans actual) {
+ return new ListOfSpansAssert(actual);
+ }
+
+ public ListOfSpansAssert thereIsOnlyOneServerAndClientSideSpanWhoseParentIdIsEqualTo(long traceId) {
+ isNotNull();
+ printSpans();
+ List spansWithParentSpanAsRootSpan = this.actual.spans.stream().filter(span -> span.getParents().contains(traceId)).collect(Collectors.toList());
+ Assertions.assertThat(spansWithParentSpanAsRootSpan).hasSize(2).extracting("spanId").containsOnly(spansWithParentSpanAsRootSpan.get(0).getSpanId());
+ return this;
+ }
+
+ public ListOfSpansAssert everyParentIdHasItsCorrespondingSpan() {
+ isNotNull();
+ printSpans();
+ List parentSpanIds = this.actual.spans.stream().flatMap(span -> span.getParents().stream())
+ .distinct().collect(Collectors.toList());
+ List spanIds = this.actual.spans.stream()
+ .map(Span::getSpanId).distinct()
+ .collect(Collectors.toList());
+ List difference = new ArrayList<>(parentSpanIds);
+ difference.removeAll(spanIds);
+ log.info("Difference between parent ids and span ids " +
+ difference.stream().map(span -> "id as long [" + span + "] and as hex [" + Span.idToHex(span) + "]").collect(Collectors.joining("\n")));
+ Assertions.assertThat(spanIds).containsAll(parentSpanIds);
+ return this;
+ }
+
+ private void printSpans() {
+ try {
+ log.info("Stored spans " + this.objectMapper.writeValueAsString(this.actual.spans));
+ }
+ catch (JsonProcessingException e) {
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SleuthAssertions.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SleuthAssertions.java
index bc1369f36..8dc550447 100644
--- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SleuthAssertions.java
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/assertions/SleuthAssertions.java
@@ -13,4 +13,13 @@ public class SleuthAssertions extends BDDAssertions {
return new SpanAssert(actual);
}
+
+ public static ListOfSpansAssert then(ListOfSpans actual) {
+ return assertThat(actual);
+ }
+
+ public static ListOfSpansAssert assertThat(ListOfSpans actual) {
+ return new ListOfSpansAssert(actual);
+ }
+
}
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterTests.java
index a42fbcd7a..0add851d1 100644
--- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterTests.java
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceFilterTests.java
@@ -171,6 +171,39 @@ public class TraceFilterTests {
this.spanExtractor, this.spanInjector, this.httpTraceKeysInjector);
filter.doFilter(this.request, this.response, this.filterChain);
+ then(TestSpanContextHolder.getCurrentSpan()).isNull();
+ then(this.request.getAttribute(TraceFilter.TRACE_ERROR_HANDLED_REQUEST_ATTR)).isNull();
+ }
+
+ @Test
+ public void closesSpanInRequestAttrIfStatusCodeNotSuccessful() throws Exception {
+ Span span = this.tracer.createSpan("http:foo");
+ this.request.setAttribute(TraceFilter.TRACE_REQUEST_ATTR, span);
+ this.response.setStatus(404);
+ // It should have been removed from the thread local context so simulate that
+ TestSpanContextHolder.removeCurrentSpan();
+
+ TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, this.spanReporter,
+ this.spanExtractor, this.spanInjector, this.httpTraceKeysInjector);
+ filter.doFilter(this.request, this.response, this.filterChain);
+
+ then(TestSpanContextHolder.getCurrentSpan()).isNull();
+ then(this.request.getAttribute(TraceFilter.TRACE_ERROR_HANDLED_REQUEST_ATTR)).isNotNull();
+ }
+
+ @Test
+ public void doesntDetachASpanIfStatusCodeNotSuccessfulAndRequestWasProcessed() throws Exception {
+ Span span = this.tracer.createSpan("http:foo");
+ this.request.setAttribute(TraceFilter.TRACE_REQUEST_ATTR, span);
+ this.request.setAttribute(TraceFilter.TRACE_ERROR_HANDLED_REQUEST_ATTR, true);
+ this.response.setStatus(404);
+ // It should have been removed from the thread local context so simulate that
+ TestSpanContextHolder.removeCurrentSpan();
+
+ TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, this.spanReporter,
+ this.spanExtractor, this.spanInjector, this.httpTraceKeysInjector);
+ filter.doFilter(this.request, this.response, this.filterChain);
+
then(TestSpanContextHolder.getCurrentSpan()).isNull();
}
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/WebClientTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/WebClientTests.java
index b068de9e6..32931d4eb 100644
--- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/WebClientTests.java
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/WebClientTests.java
@@ -58,7 +58,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Component;
import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;
import org.springframework.web.bind.annotation.RequestHeader;
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactoryTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactoryTest.java
index 2930b531f..4f58d3bfe 100644
--- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactoryTest.java
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceRestClientRibbonCommandFactoryTest.java
@@ -16,10 +16,8 @@
package org.springframework.cloud.sleuth.instrument.zuul;
-import static org.assertj.core.api.BDDAssertions.then;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
+import com.netflix.client.http.HttpRequest;
+import com.netflix.niws.client.http.RestClient;
import org.junit.Before;
import org.junit.Test;
@@ -32,9 +30,12 @@ import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanInjector;
import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.instrument.web.HttpTraceKeysInjector;
-import com.netflix.client.http.HttpRequest;
-import com.netflix.niws.client.http.RestClient;
+import static org.assertj.core.api.BDDAssertions.then;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
/**
* @author Marcin Grzejszczak
@@ -42,18 +43,18 @@ import com.netflix.niws.client.http.RestClient;
@RunWith(MockitoJUnitRunner.class)
public class TraceRestClientRibbonCommandFactoryTest {
- @Mock
- Tracer tracer;
- @Mock
- SpringClientFactory springClientFactory;
+ @Mock Tracer tracer;
+ @Mock SpringClientFactory springClientFactory;
SpanInjector spanInjector = new RequestBuilderContextInjector();
+ @Mock HttpTraceKeysInjector httpTraceKeysInjector;
TraceRestClientRibbonCommandFactory traceRestClientRibbonCommandFactory;
@Before
@SuppressWarnings({ "deprecation", "unchecked" })
public void setup() {
this.traceRestClientRibbonCommandFactory = new TraceRestClientRibbonCommandFactory(
- this.springClientFactory, this.tracer, this.spanInjector);
+ this.springClientFactory, this.tracer, this.spanInjector,
+ httpTraceKeysInjector);
given(this.springClientFactory.getClient(anyString(), any(Class.class)))
.willReturn(new RestClient());
Span span = Span.builder().name("name").spanId(1L).traceId(2L).parent(3L)
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulIntegrationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulIntegrationTests.java
new file mode 100644
index 000000000..24a184eaa
--- /dev/null
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/zuul/TraceZuulIntegrationTests.java
@@ -0,0 +1,157 @@
+package org.springframework.cloud.sleuth.instrument.zuul;
+
+import java.io.IOException;
+
+import com.netflix.loadbalancer.Server;
+import com.netflix.loadbalancer.ServerList;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.IntegrationTest;
+import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.cloud.netflix.ribbon.RibbonClient;
+import org.springframework.cloud.netflix.ribbon.StaticServerList;
+import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
+import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
+import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
+import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator;
+import org.springframework.cloud.sleuth.Sampler;
+import org.springframework.cloud.sleuth.Span;
+import org.springframework.cloud.sleuth.SpanReporter;
+import org.springframework.cloud.sleuth.Tracer;
+import org.springframework.cloud.sleuth.assertions.ListOfSpans;
+import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
+import org.springframework.cloud.sleuth.util.ArrayListSpanAccumulator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.DefaultResponseErrorHandler;
+import org.springframework.web.client.RestTemplate;
+
+import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringApplicationConfiguration(classes = SampleZuulProxyApplication.class)
+@WebAppConfiguration
+@IntegrationTest({ "server.port: 0", "zuul.routes.simple: /simple/**", "hystrix.command.default.execution.isolation.strategy: SEMAPHORE"})
+@DirtiesContext
+public class TraceZuulIntegrationTests {
+
+ @Value("${local.server.port}")
+ private int port;
+ @Autowired Tracer tracer;
+ @Autowired ArrayListSpanAccumulator spanAccumulator;
+ @Autowired RestTemplate restTemplate;
+
+ @Before
+ public void cleanup() {
+ this.spanAccumulator.getSpans().clear();
+ }
+
+ @Test
+ public void should_close_span_when_routing_to_service_via_discovery() {
+ Span span = this.tracer.createSpan("new_span");
+ ResponseEntity result = this.restTemplate.exchange(
+ "http://localhost:" + this.port + "/simple/", HttpMethod.GET,
+ new HttpEntity<>((Void) null), String.class);
+
+ this.tracer.close(span);
+
+ then(result.getStatusCode()).isEqualTo(HttpStatus.OK);
+ then(result.getBody()).isEqualTo("Hello world");
+ then(this.tracer.getCurrentSpan()).isNull();
+ then(new ListOfSpans(this.spanAccumulator.getSpans()))
+ .thereIsOnlyOneServerAndClientSideSpanWhoseParentIdIsEqualTo(span.getTraceId());
+ }
+
+ @Test
+ public void should_close_span_when_routing_to_service_via_discovery_to_a_non_existent_url() {
+ Span span = this.tracer.createSpan("new_span");
+ ResponseEntity result = this.restTemplate.exchange(
+ "http://localhost:" + this.port + "/simple/nonExistentUrl", HttpMethod.GET,
+ new HttpEntity<>((Void) null), String.class);
+
+ this.tracer.close(span);
+
+ then(result.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
+ then(this.tracer.getCurrentSpan()).isNull();
+ then(new ListOfSpans(this.spanAccumulator.getSpans()))
+ .thereIsOnlyOneServerAndClientSideSpanWhoseParentIdIsEqualTo(span.getTraceId())
+ .everyParentIdHasItsCorrespondingSpan();
+ }
+}
+
+// Don't use @SpringBootApplication because we don't want to component scan
+@Configuration
+@EnableAutoConfiguration
+@RestController
+@EnableZuulProxy
+@RibbonClient(name = "simple", configuration = SimpleRibbonClientConfiguration.class)
+class SampleZuulProxyApplication {
+
+
+ @RequestMapping("/")
+ public String home() {
+ return "Hello world";
+ }
+
+ @RequestMapping("/exception")
+ public String exception() {
+ throw new RuntimeException();
+ }
+
+ @Bean RouteLocator routeLocator(DiscoveryClient discoveryClient, ZuulProperties zuulProperties) {
+ return new MyRouteLocator("/", discoveryClient, zuulProperties);
+ }
+
+ @Bean SpanReporter testSpanReporter() {
+ return new ArrayListSpanAccumulator();
+ }
+
+ @Bean RestTemplate restTemplate() {
+ RestTemplate restTemplate = new RestTemplate();
+ restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
+ @Override public void handleError(ClientHttpResponse response)
+ throws IOException {
+
+ }
+ });
+ return restTemplate;
+ }
+
+ @Bean Sampler alwaysSampler() {
+ return new AlwaysSampler();
+ }
+}
+
+class MyRouteLocator extends DiscoveryClientRouteLocator {
+
+ public MyRouteLocator(String servletPath, DiscoveryClient discovery, ZuulProperties properties) {
+ super(servletPath, discovery, properties);
+ }
+}
+
+// Load balancer with fixed server list for "simple" pointing to localhost
+@Configuration
+class SimpleRibbonClientConfiguration {
+
+ @Value("${local.server.port}") private int port;
+
+ @Bean public ServerList ribbonServerList() {
+ return new StaticServerList<>(new Server("localhost", this.port));
+ }
+}
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/Slf4JSpanLoggerTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/Slf4JSpanLoggerTest.java
index d6ddb6a27..29b3afea6 100644
--- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/Slf4JSpanLoggerTest.java
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/log/Slf4JSpanLoggerTest.java
@@ -16,11 +16,13 @@
package org.springframework.cloud.sleuth.log;
+import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.springframework.cloud.sleuth.Span;
+import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Matchers.anyList;
import static org.mockito.Matchers.anyString;
@@ -38,6 +40,11 @@ public class Slf4JSpanLoggerTest {
Logger log = Mockito.mock(Logger.class);
Slf4jSpanLogger slf4JSpanLogger = new Slf4jSpanLogger(this.nameExcludingPattern, this.log);
+ @Before
+ public void setup() {
+ given(log.isTraceEnabled()).willReturn(true);
+ }
+
@Test
public void should_log_when_start_event_arrived_and_pattern_doesnt_match_span_name() throws Exception {
this.slf4JSpanLogger.logStartedSpan(this.spanWithNameNotToBeExcluded,
diff --git a/spring-cloud-sleuth-core/src/test/resources/application.yml b/spring-cloud-sleuth-core/src/test/resources/application.yml
index 08eb3a3ec..d081e7e83 100644
--- a/spring-cloud-sleuth-core/src/test/resources/application.yml
+++ b/spring-cloud-sleuth-core/src/test/resources/application.yml
@@ -11,4 +11,4 @@ exceptionService.ribbon:
spring.sleuth.scheduled.skipPattern: "^org.*TestBeanWithScheduledMethodToBeIgnored$"
# comma separated list of matchers
-spring.sleuth.rxjava.schedulers.ignoredthreads: HystixMetricPoller,^MyCustomThread.*$
\ No newline at end of file
+spring.sleuth.rxjava.schedulers.ignoredthreads: HystixMetricPoller,^MyCustomThread.*$,^RxComputation.*$
\ No newline at end of file
diff --git a/spring-cloud-sleuth-core/src/test/resources/logback.xml b/spring-cloud-sleuth-core/src/test/resources/logback.xml
index 76eafe455..307883eea 100644
--- a/spring-cloud-sleuth-core/src/test/resources/logback.xml
+++ b/spring-cloud-sleuth-core/src/test/resources/logback.xml
@@ -1,7 +1,10 @@
-
+
+
+
+
diff --git a/spring-cloud-sleuth-dependencies/pom.xml b/spring-cloud-sleuth-dependencies/pom.xml
index 0695d7a75..bbe983cc9 100644
--- a/spring-cloud-sleuth-dependencies/pom.xml
+++ b/spring-cloud-sleuth-dependencies/pom.xml
@@ -14,7 +14,7 @@
spring-cloud-sleuth-dependencies
Spring Cloud Sleuth Dependencies
- 1.1.1.BUILD-SNAPSHOT
+ 1.1.2.BUILD-SNAPSHOT
1.8.4
1.1.1