Separate parent and child a bit more in ZipkinSpanListener

This commit is contained in:
Dave Syer
2015-07-29 13:52:31 +01:00
parent 145cc641c2
commit af03054573
10 changed files with 75 additions and 63 deletions

View File

@@ -6,7 +6,7 @@ import lombok.Data;
* @author Spencer Gibb
*/
@Data
public class TraceInfo implements SpanIdentifiers {
public class BasicSpanIdentifiers implements SpanIdentifiers {
private final String traceId;
private final String spanId;
private String processId;

View File

@@ -39,26 +39,27 @@ public class TraceScope implements Closeable {
}
/**
* Remove this span as the current thread, but don't stop it yet or
* send it for collection. This is useful if the span object is then
* passed to another thread for use with Trace.continueTrace().
* Remove this span as the current thread, but don't stop it yet or send it for
* collection. This is useful if the span object is then passed to another thread for
* use with Trace.continueTrace().
*
* @return the same Span object
*/
public SpanIdentifiers detach() {
if (this.detached) {
ExceptionUtils.error("Tried to detach trace span " + this.span + " but " +
"it has already been detached.");
ExceptionUtils.error("Tried to detach trace span " + this.span + " but "
+ "it has already been detached.");
}
this.detached = true;
SpanIdentifiers cur = TraceContextHolder.getCurrentSpan();
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 {
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(this.savedSpan);
}
return this.span;
@@ -73,13 +74,19 @@ public class TraceScope implements Closeable {
this.detached = true;
SpanIdentifiers cur = TraceContextHolder.getCurrentSpan();
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 {
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 {
this.span.stop();
this.publisher.publishEvent(new SpanStoppedEvent(this, this.span));
if (this.savedSpan != null && this.span.getParents().contains(this.savedSpan.getSpanId())) {
this.publisher.publishEvent(new SpanStoppedEvent(this, this.savedSpan, this.span));
}
else {
this.publisher.publishEvent(new SpanStoppedEvent(this, this.span));
}
TraceContextHolder.setCurrentSpan(this.savedSpan);
}
}

View File

@@ -1,23 +1,30 @@
package org.springframework.cloud.sleuth.event;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Value;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanIdentifiers;
import org.springframework.context.ApplicationEvent;
/**
* @author Spencer Gibb
*/
@Value
@Data
@EqualsAndHashCode(callSuper=false)
@SuppressWarnings("serial")
public class SpanStartedEvent extends ApplicationEvent {
private final SpanIdentifiers parent;
private final Span span;
public SpanStartedEvent(Object source, Span span) {
this(source, null, span);
}
public SpanStartedEvent(Object source, SpanIdentifiers parent, Span span) {
super(source);
this.parent = parent;
this.span = span;
}
}

View File

@@ -1,23 +1,30 @@
package org.springframework.cloud.sleuth.event;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Value;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanIdentifiers;
import org.springframework.context.ApplicationEvent;
/**
* @author Spencer Gibb
*/
@Value
@Data
@EqualsAndHashCode(callSuper=false)
@SuppressWarnings("serial")
public class SpanStoppedEvent extends ApplicationEvent {
private final Span span;
private final SpanIdentifiers parent;
public SpanStoppedEvent(Object source, Span span) {
this(source, null, span);
}
public SpanStoppedEvent(Object source, SpanIdentifiers parent, Span span) {
super(source);
this.parent = parent;
this.span = span;
}
}

View File

@@ -27,8 +27,8 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.cloud.sleuth.BasicSpanIdentifiers;
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;
@@ -72,17 +72,17 @@ public class TraceFilter extends OncePerRequestFilter {
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String uri = hasText(request.getRequestURI()) ? request.getRequestURI() : "";
String uri = this.urlPathHelper.getPathWithinApplication(request);
boolean skip = this.skipPattern.matcher(uri).matches();
TraceScope traceScope = null;
if (!skip) {
String spanId = getHeader(request, response, SPAN_ID_NAME);
String traceId = getHeader(request, response, TRACE_ID_NAME);
String name = "http" + this.urlPathHelper.getPathWithinApplication(request);
String name = "http" + uri;
if (hasText(spanId) && hasText(traceId)) {
TraceInfo traceInfo = new TraceInfo(traceId, spanId);
BasicSpanIdentifiers traceInfo = new BasicSpanIdentifiers(traceId, spanId);
// TODO: trace description?
traceScope = this.trace.startSpan(name, traceInfo);
// Send new span id back

View File

@@ -7,7 +7,7 @@ import static org.springframework.util.StringUtils.hasText;
import javax.servlet.http.HttpServletRequest;
import org.springframework.cloud.sleuth.Trace;
import org.springframework.cloud.sleuth.TraceInfo;
import org.springframework.cloud.sleuth.BasicSpanIdentifiers;
import org.springframework.cloud.sleuth.TraceScope;
import com.netflix.zuul.ZuulFilter;
@@ -49,7 +49,7 @@ public class TracePreFilter extends ZuulFilter {
TraceScope traceScope = null;
if (hasText(spanId) && hasText(traceId)) {
TraceInfo traceInfo = new TraceInfo(traceId, spanId);
BasicSpanIdentifiers traceInfo = new BasicSpanIdentifiers(traceId, spanId);
// TODO: trace description?
traceScope = trace.startSpan("traceZuulFilter", traceInfo);
}

View File

@@ -47,7 +47,7 @@ public class DefaultTrace implements Trace {
+ " tried to start a new Span " + "with parent " + parent.toString()
+ ", but there is already a " + "currentSpan " + currentSpan);
}
return doStart(createChild(parent, name));
return continueSpan(createChild(parent, name));
}
@Override
@@ -61,30 +61,27 @@ public class DefaultTrace implements Trace {
if (TraceContextHolder.isTracing() || s.next(info)) {
span = createChild(getCurrentSpan(), name);
}
return doStart(span);
return continueSpan(span);
}
protected Span createChild(SpanIdentifiers parent, String name) {
if (parent == null) {
return MilliSpan.builder().begin(System.currentTimeMillis()).name(name)
MilliSpan span = MilliSpan.builder().begin(System.currentTimeMillis()).name(name)
.traceId(this.idGenerator.create()).spanId(this.idGenerator.create())
.build();
this.publisher.publishEvent(new SpanStartedEvent(this, span));
return span;
}
else {
return MilliSpan.builder().begin(System.currentTimeMillis()).name(name)
MilliSpan span = MilliSpan.builder().begin(System.currentTimeMillis()).name(name)
.traceId(parent.getTraceId()).parent(parent.getSpanId())
.spanId(this.idGenerator.create()).processId(parent.getProcessId())
.build();
this.publisher.publishEvent(new SpanStartedEvent(this, parent, span));
return span;
}
}
protected TraceScope doStart(Span span) {
if (span != null) {
this.publisher.publishEvent(new SpanStartedEvent(this, span));
}
return continueSpan(span);
}
@Override
public TraceScope continueSpan(Span span) {
// Return an empty TraceScope that does nothing on close

View File

@@ -34,6 +34,10 @@ public class SampleApplication {
SpringApplication.run(SampleApplication.class, args);
}
//@Bean public SpanCollector spanCollector() { return new LoggingSpanCollectorImpl(); }
// Use this for debugging (or if there is no Zipkin collector running on port 9410)
// @Bean
// public SpanCollector spanCollector() {
// return new LoggingSpanCollectorImpl();
// }
}

View File

@@ -41,8 +41,8 @@ import com.google.common.base.Optional;
public class ZipkinAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SpanCollector spanCollector() {
@ConditionalOnMissingBean(SpanCollector.class)
public ZipkinSpanCollector spanCollector() {
return new ZipkinSpanCollector(zipkinProperties().getHost(), zipkinProperties()
.getPort());
}

View File

@@ -3,8 +3,8 @@ package org.springframework.cloud.sleuth.zipkin;
import lombok.Data;
import lombok.extern.apachecommons.CommonsLog;
import org.springframework.cloud.sleuth.SpanIdentifiers;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanIdentifiers;
import org.springframework.cloud.sleuth.event.SpanStartedEvent;
import org.springframework.cloud.sleuth.event.SpanStoppedEvent;
import org.springframework.context.event.EventListener;
@@ -25,23 +25,20 @@ public class ZipkinSpanListener {
@EventListener
public void start(SpanStartedEvent event) {
preTrace(event.getSpan());
preTrace(event.getParent(), event.getSpan());
}
@EventListener
public void start(SpanStoppedEvent event) {
postTrace(event.getSpan());
public void stop(SpanStoppedEvent event) {
postTrace(event.getParent(), event.getSpan());
}
protected void preTrace(Span context) {
final TraceData traceData = getTraceData(context);
final String spanName = getSpanName(context, traceData);
if (traceData.getTraceId() != null && traceData.getSpanId() != null) {
protected void preTrace(SpanIdentifiers parent, Span span) {
String spanName = span.getName();
if (span.getTraceId() != null && span.getSpanId() != null) {
log.debug("Received span information as part of request.");
this.serverTracer.setStateCurrentTrace(traceData.getTraceId(),
traceData.getSpanId(), traceData.getParentSpanId(), spanName);
this.serverTracer.setStateCurrentTrace(hash(span.getTraceId()),
getSpanId(span), getSpanId(parent), spanName);
}
else {
log.debug("Received no span state.");
@@ -50,22 +47,15 @@ public class ZipkinSpanListener {
this.serverTracer.setServerReceived();
}
protected TraceData getTraceData(Span context) {
TraceData trace = new TraceData();
trace.setTraceId(hash(context.getTraceId()));
trace.setSpanId(hash(context.getSpanId()));
trace.setSpanName(context.getName());
if (!context.getParents().isEmpty()) {
trace.setParentSpanId(hash(context.getParents().iterator().next()));
}
return trace;
private Long getSpanId(SpanIdentifiers span) {
return span == null ? null : hash(span.getSpanId());
}
protected String getSpanName(Span context, TraceData traceData) {
return context.getName();
}
protected void postTrace(SpanIdentifiers context) {
protected void postTrace(SpanIdentifiers parent, Span span) {
// We can submit this in any case. When server state is not set or
// we should not trace this request nothing will happen.
log.debug("Sending server send.");