Integrate server-side zipkin with core
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
package org.springframework.cloud.sleuth;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.Value;
|
||||
import lombok.experimental.NonFinal;
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
|
||||
import org.springframework.cloud.sleuth.event.SpanStoppedEvent;
|
||||
import org.springframework.cloud.sleuth.util.ExceptionUtils;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
/**
|
||||
@@ -14,6 +18,7 @@ import org.springframework.context.ApplicationEventPublisher;
|
||||
*/
|
||||
@Value
|
||||
@NonFinal
|
||||
@CommonsLog
|
||||
public class TraceScope implements Closeable {
|
||||
|
||||
private final ApplicationEventPublisher publisher;
|
||||
@@ -28,6 +33,11 @@ public class TraceScope implements Closeable {
|
||||
*/
|
||||
private final Span savedSpan;
|
||||
|
||||
/**
|
||||
* List of callbacks to run on close.
|
||||
*/
|
||||
private List<Runnable> callbacks = new ArrayList<Runnable>();
|
||||
|
||||
@NonFinal
|
||||
private boolean detached = false;
|
||||
|
||||
@@ -45,41 +55,54 @@ public class TraceScope implements Closeable {
|
||||
* @return the same Span object
|
||||
*/
|
||||
public Span detach() {
|
||||
if (detached) {
|
||||
Utils.error("Tried to detach trace span " + span + " but " +
|
||||
if (this.detached) {
|
||||
ExceptionUtils.error("Tried to detach trace span " + this.span + " but " +
|
||||
"it has already been detached.");
|
||||
}
|
||||
detached = true;
|
||||
this.detached = true;
|
||||
|
||||
Span cur = TraceContextHolder.getCurrentSpan();
|
||||
if (cur != span) {
|
||||
Utils.error("Tried to detach trace span " + span + " but " +
|
||||
if (cur != this.span) {
|
||||
ExceptionUtils.error("Tried to detach trace span " + this.span + " but " +
|
||||
"it is not the current span for the " +
|
||||
Thread.currentThread().getName() + " thread. You have " +
|
||||
"probably forgotten to close or detach " + cur);
|
||||
} else {
|
||||
TraceContextHolder.setCurrentSpan(savedSpan);
|
||||
TraceContextHolder.setCurrentSpan(this.savedSpan);
|
||||
}
|
||||
return this.span;
|
||||
}
|
||||
|
||||
public void register(Runnable callback) {
|
||||
if (!this.callbacks .contains(callback)) {
|
||||
this.callbacks.add(callback);
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void close() {
|
||||
if (detached) {
|
||||
if (this.detached) {
|
||||
return;
|
||||
}
|
||||
detached = true;
|
||||
this.detached = true;
|
||||
for (Runnable callback : this.callbacks) {
|
||||
try {
|
||||
callback.run();
|
||||
} catch (Throwable e) {
|
||||
log.error("Error with callback on close", e);
|
||||
}
|
||||
}
|
||||
Span cur = TraceContextHolder.getCurrentSpan();
|
||||
if (cur != span) {
|
||||
Utils.error("Tried to close trace span " + span + " but " +
|
||||
if (cur != this.span) {
|
||||
ExceptionUtils.error("Tried to close trace span " + this.span + " but " +
|
||||
"it is not the current span for the " +
|
||||
Thread.currentThread().getName() + " thread. You have " +
|
||||
"probably forgotten to close or detach " + cur);
|
||||
} else {
|
||||
span.stop();
|
||||
this.publisher.publishEvent(new SpanStoppedEvent(this, span));
|
||||
TraceContextHolder.setCurrentSpan(savedSpan);
|
||||
this.span.stop();
|
||||
this.publisher.publishEvent(new SpanStoppedEvent(this, this.span));
|
||||
TraceContextHolder.setCurrentSpan(this.savedSpan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package org.springframework.cloud.sleuth;
|
||||
package org.springframework.cloud.sleuth.autoconfig;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.sleuth.IdGenerator;
|
||||
import org.springframework.cloud.sleuth.RandomUuidGenerator;
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.Trace;
|
||||
import org.springframework.cloud.sleuth.sampler.IsTracingSampler;
|
||||
import org.springframework.cloud.sleuth.trace.DefaultTrace;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -20,13 +25,13 @@ public class TraceAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Sampler defaultSampler() {
|
||||
public Sampler<?> defaultSampler() {
|
||||
return new IsTracingSampler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Trace trace(Sampler sampler, IdGenerator idGenerator,
|
||||
public Trace trace(Sampler<?> sampler, IdGenerator idGenerator,
|
||||
ApplicationEventPublisher publisher) {
|
||||
return new DefaultTrace(sampler, idGenerator, publisher);
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.springframework.cloud.sleuth;
|
||||
package org.springframework.cloud.sleuth.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.cloud.sleuth.event.SpanStoppedEvent;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
/**
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.springframework.cloud.sleuth.instrument;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
@@ -10,6 +11,7 @@ import org.springframework.cloud.sleuth.TraceScope;
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Value
|
||||
@EqualsAndHashCode(callSuper=false)
|
||||
public class TraceRunnable extends TraceDelegate<Runnable> implements Runnable {
|
||||
|
||||
public TraceRunnable(Trace trace, Runnable delagate) {
|
||||
|
||||
@@ -30,6 +30,8 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.cloud.sleuth.Trace;
|
||||
import org.springframework.cloud.sleuth.TraceInfo;
|
||||
import org.springframework.cloud.sleuth.TraceScope;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
@@ -44,6 +46,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE + 5)
|
||||
public class TraceFilter extends OncePerRequestFilter {
|
||||
|
||||
public static final Pattern DEFAULT_SKIP_PATTERN = Pattern
|
||||
@@ -65,10 +68,10 @@ public class TraceFilter extends OncePerRequestFilter {
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
throws ServletException, IOException {
|
||||
|
||||
String uri = hasText(request.getRequestURI()) ? request.getRequestURI() : "";
|
||||
boolean skip = skipPattern.matcher(uri).matches();
|
||||
boolean skip = this.skipPattern.matcher(uri).matches();
|
||||
|
||||
TraceScope traceScope = null;
|
||||
if (!skip) {
|
||||
@@ -78,13 +81,13 @@ public class TraceFilter extends OncePerRequestFilter {
|
||||
|
||||
TraceInfo traceInfo = new TraceInfo(traceId, spanId);
|
||||
// TODO: trace description?
|
||||
traceScope = trace.startSpan("traceFilter", traceInfo);
|
||||
traceScope = this.trace.startSpan("traceFilter", traceInfo);
|
||||
// Send new span id back
|
||||
addToResponseIfNotPresent(response, SPAN_ID_NAME, traceScope.getSpan()
|
||||
.getSpanId());
|
||||
}
|
||||
else {
|
||||
traceScope = trace.startSpan("traceFilter");
|
||||
traceScope = this.trace.startSpan("traceFilter");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,12 +67,12 @@ public class TraceWebAspect {
|
||||
@Around("anyControllerOrRestControllerWithPublicAsyncMethod()")
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object wrapWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable {
|
||||
Callable callable = (Callable) pjp.proceed();
|
||||
Callable<Object> callable = (Callable<Object>) pjp.proceed();
|
||||
if (TraceContextHolder.isTracing()) {
|
||||
log.debug("Wrapping callable with span ["
|
||||
+ TraceContextHolder.getCurrentSpan() + "]");
|
||||
|
||||
return new TraceCallable(this.trace, callable);
|
||||
return new TraceCallable<Object>(this.trace, callable);
|
||||
}
|
||||
else {
|
||||
return callable;
|
||||
|
||||
@@ -27,8 +27,6 @@ import org.springframework.cloud.sleuth.Trace;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* Registers beans that add tracing to requests
|
||||
@@ -55,41 +53,15 @@ public class TraceWebAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TraceWebAspect traceWebAspect() {
|
||||
return new TraceWebAspect(trace);
|
||||
return new TraceWebAspect(this.trace);
|
||||
}
|
||||
|
||||
//TODO: I don't think TraceHandlerInterceptor is needed with TraceFilter
|
||||
/*@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TraceHandlerInterceptor traceHandlerInterceptor() {
|
||||
return new TraceHandlerInterceptor(trace);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebMvcConfigurerAdapter webMvcConfigurerAdapter(
|
||||
TraceHandlerInterceptor handlerInterceptor) {
|
||||
return new TraceWebConfigurer(handlerInterceptor);
|
||||
}
|
||||
|
||||
protected static class TraceWebConfigurer extends WebMvcConfigurerAdapter {
|
||||
private TraceHandlerInterceptor interceptor;
|
||||
|
||||
public TraceWebConfigurer(TraceHandlerInterceptor interceptor) {
|
||||
this.interceptor = interceptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(interceptor).addPathPatterns("/**");
|
||||
}
|
||||
}*/
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public FilterRegistrationBean traceFilter() {
|
||||
Pattern pattern = StringUtils.hasText(skipPattern) ? Pattern.compile(skipPattern)
|
||||
Pattern pattern = StringUtils.hasText(this.skipPattern) ? Pattern.compile(this.skipPattern)
|
||||
: TraceFilter.DEFAULT_SKIP_PATTERN;
|
||||
return new FilterRegistrationBean(new TraceFilter(trace, pattern));
|
||||
return new FilterRegistrationBean(new TraceFilter(this.trace, pattern));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
package org.springframework.cloud.sleuth;
|
||||
package org.springframework.cloud.sleuth.trace;
|
||||
|
||||
import static org.springframework.cloud.sleuth.Utils.error;
|
||||
import static org.springframework.cloud.sleuth.util.ExceptionUtils.error;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.springframework.cloud.sleuth.IdGenerator;
|
||||
import org.springframework.cloud.sleuth.MilliSpan;
|
||||
import org.springframework.cloud.sleuth.NullScope;
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Trace;
|
||||
import org.springframework.cloud.sleuth.TraceContextHolder;
|
||||
import org.springframework.cloud.sleuth.TraceInfo;
|
||||
import org.springframework.cloud.sleuth.TraceScope;
|
||||
import org.springframework.cloud.sleuth.event.SpanStartedEvent;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceCallable;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceRunnable;
|
||||
@@ -30,7 +38,7 @@ public class DefaultTrace implements Trace {
|
||||
|
||||
@Override
|
||||
public TraceScope startSpan(String name) {
|
||||
return this.startSpan(name, defaultSampler);
|
||||
return this.startSpan(name, this.defaultSampler);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,7 +48,7 @@ public class DefaultTrace implements Trace {
|
||||
.begin(System.currentTimeMillis())
|
||||
.name(name)
|
||||
.traceId(tinfo.getTraceId())
|
||||
.spanId(idGenerator.create())
|
||||
.spanId(this.idGenerator.create())
|
||||
.parent(tinfo.getSpanId())
|
||||
.build();
|
||||
return doStart(span);
|
||||
@@ -81,8 +89,8 @@ public class DefaultTrace implements Trace {
|
||||
return MilliSpan.builder()
|
||||
.begin(System.currentTimeMillis())
|
||||
.name(name)
|
||||
.traceId(idGenerator.create())
|
||||
.spanId(idGenerator.create())
|
||||
.traceId(this.idGenerator.create())
|
||||
.spanId(this.idGenerator.create())
|
||||
.build();
|
||||
} else {
|
||||
return createChild(parent, name);
|
||||
@@ -95,14 +103,14 @@ public class DefaultTrace implements Trace {
|
||||
.name(childname)
|
||||
.traceId(parent.getTraceId())
|
||||
.parent(parent.getSpanId())
|
||||
.spanId(idGenerator.create())
|
||||
.spanId(this.idGenerator.create())
|
||||
.processId(parent.getProcessId())
|
||||
.build();
|
||||
}
|
||||
|
||||
protected TraceScope doStart(Span span) {
|
||||
if (span != null) {
|
||||
publisher.publishEvent(new SpanStartedEvent(this, span));
|
||||
this.publisher.publishEvent(new SpanStartedEvent(this, span));
|
||||
}
|
||||
return continueSpan(span);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.cloud.sleuth;
|
||||
package org.springframework.cloud.sleuth.util;
|
||||
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
|
||||
@@ -6,7 +6,7 @@ import lombok.extern.apachecommons.CommonsLog;
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
@CommonsLog
|
||||
public abstract class Utils {
|
||||
public abstract class ExceptionUtils {
|
||||
public static void error(String msg) {
|
||||
log.error(msg);
|
||||
throw new RuntimeException(msg);
|
||||
@@ -1,6 +1,6 @@
|
||||
# Auto Configuration
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.sleuth.TraceAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.slf4j.SleuthSlf4jAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.instrument.web.TraceWebAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.springframework.cloud.sleuth.event.SpanStartedEvent;
|
||||
import org.springframework.cloud.sleuth.event.SpanStoppedEvent;
|
||||
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
|
||||
import org.springframework.cloud.sleuth.sampler.IsTracingSampler;
|
||||
import org.springframework.cloud.sleuth.trace.DefaultTrace;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user