Merge pull request #212 from spring-cloud/issues_#156_refactor_events

Removed events and replaced them with method calls
This commit is contained in:
Marcin Grzejszczak
2016-03-13 10:56:57 +01:00
66 changed files with 529 additions and 938 deletions

View File

@@ -9,9 +9,6 @@ before_install:
- echo "https://$GH_TOKEN:@github.com" > .git/credentials
- gem install asciidoctor
install:
- ./mvnw install -P docs -q -U -DskipTests=true -Dmaven.test.redirectTestOutputToFile=true
- '[ "${MVN_GOAL}" == "deploy" ] && ./docs/src/main/asciidoc/ghpages.sh || echo "Not updating docs"'
script:
- |
cat <<EOF
@@ -23,15 +20,21 @@ script:
VERSION=${VERSION}
MILESTONE=${MILESTONE}
MVN_PROFILE=${MVN_PROFILE}
TRAVIS_BRANCH=${TRAVIS_BRANCH}
TRAVIS_REPO_SLUG=${TRAVIS_REPO_SLUG}
TRAVIS_PULL_REQUEST=${TRAVIS_PULL_REQUEST}
EOF
- ./mvnw install -P docs -q -U -DskipTests=true -Dmaven.test.redirectTestOutputToFile=true
- '[ "${MVN_GOAL}" == "deploy" ] && ./docs/src/main/asciidoc/ghpages.sh || echo "Not updating docs"'
script:
- './mvnw -s .settings.xml $MVN_GOAL $MVN_PROFILE -nsu -Dmaven.test.redirectTestOutputToFile=true'
env:
global:
- GIT_NAME="Spencer Gibb"
- GIT_EMAIL=sgibb@pivotal.io
- CI_DEPLOY_USERNAME=sgibb
- FEATURE_BRANCH=$(echo ${TRAVIS_BRANCH} | grep "^.*/.*$" && echo true || echo false)
- FEATURE_BRANCH=$(echo ${TRAVIS_BRANCH} | grep -v "master" && echo true || echo false)
- SPRING_CLOUD_BUILD=$(echo ${TRAVIS_REPO_SLUG} | grep -q "^spring-cloud/.*$" && echo true || echo false)
- MVN_GOAL=$([ "${TRAVIS_PULL_REQUEST}" == "false" -a "${TRAVIS_TAG}" == "" -a "${FEATURE_BRANCH}" == "false" -a "${SPRING_CLOUD_BUILD}" == "true" ] && echo deploy || echo install)
- VERSION=$(mvn validate | grep Building | head -1 | sed -e 's/.* //')

View File

@@ -52,4 +52,11 @@ public class Log {
public String getEvent() {
return this.event;
}
@Override public String toString() {
return "Log{" +
"timestamp=" + this.timestamp +
", event='" + this.event + '\'' +
'}';
}
}

View File

@@ -14,20 +14,18 @@
* limitations under the License.
*/
package org.springframework.cloud.sleuth.event;
import org.springframework.cloud.sleuth.Span;
package org.springframework.cloud.sleuth;
/**
* Emitted when a span was continued.
* Span reporter that does nothing
*
* @author Spencer Gibb
* @author Marcin Grzejszczak
*
* @since 1.0.0
*/
@SuppressWarnings("serial")
public class SpanContinuedEvent extends SpanContainingEvent {
public class NoOpSpanReporter implements SpanReporter {
@Override
public void report(Span span) {
public SpanContinuedEvent(Object source, Span span) {
super(source, span);
}
}

View File

@@ -39,10 +39,10 @@ import org.springframework.util.StringUtils;
* of the core annotations used to define the start and stop of a request:
* <p>
* <ul>
* <li><b>cs</b> - {@link org.springframework.cloud.sleuth.event.ClientSentEvent Client Sent}</li>
* <li><b>sr</b> - {@link org.springframework.cloud.sleuth.event.ServerReceivedEvent Server Received}</li>
* <li><b>ss</b> - {@link org.springframework.cloud.sleuth.event.ServerSentEvent Server Sent}</li>
* <li><b>cr</b> - {@link org.springframework.cloud.sleuth.event.ClientReceivedEvent Client Received}</li>
* <li><b>cs</b> - Client Sent</li>
* <li><b>sr</b> - Server Received</li>
* <li><b>ss</b> - Server Sent</li>
* <li><b>cr</b> - Client Received</li>
* </ul>
*
* @author Spencer Gibb
@@ -63,7 +63,41 @@ public class Span {
public static final String SPAN_NAME_NAME = "X-Span-Name";
public static final String SPAN_ID_NAME = "X-Span-Id";
public static final String SPAN_EXPORT_NAME = "X-Span-Export";
public static final String SPAN_LOCAL_COMPONENT_TAG_NAME = "lc";
/**
* <b>cr</b> - Client Receive. Signifies the end of the span. The client has successfully received the
* response from the server side. If one subtracts the cs timestamp from this timestamp one
* will receive the whole time needed by the client to receive the response from the server.
*/
public static final String CLIENT_RECV = "cr";
/**
* <b>cs</b> - Client Sent. The client has made a request (a client can be e.g.
* {@link org.springframework.web.client.RestTemplate}. This annotation depicts
* the start of the span.
*/
// For an outbound RPC call, it should log a "cs" annotation.
// If possible, it should log a binary annotation of "sa", indicating the
// destination address.
public static final String CLIENT_SEND = "cs";
/**
* <b>sr</b> - Server Receive. The server side got the request and will start processing it.
* If one subtracts the cs timestamp from this timestamp one will receive the network latency.
*/
// If an inbound RPC call, it should log a "sr" annotation.
// If possible, it should log a binary annotation of "ca", indicating the
// caller's address (ex X-Forwarded-For header)
public static final String SERVER_RECV = "sr";
/**
* <b>ss</b> - Server Send. Annotated upon completion of request processing (when the response
* got sent back to the client). If one subtracts the sr timestamp from this timestamp one
* will receive the time needed by the server side to process the request.
*/
public static final String SERVER_SEND = "ss";
/**
* <a href="https://github.com/opentracing/opentracing-go/blob/master/ext/tags.go">As in Open Tracing</a>
*/

View File

@@ -14,23 +14,19 @@
* limitations under the License.
*/
package org.springframework.cloud.sleuth.event;
import org.springframework.cloud.sleuth.Span;
package org.springframework.cloud.sleuth;
/**
* <b>cs</b> - Client Sent. The client has made a request (a client can be e.g.
* {@link org.springframework.web.client.RestTemplate}. This annotation depicts
* the start of the span.
* Contract for reporting Sleuth spans for collection. For example to Zipkin.
*
* @author Marcin Grzejszczak
*
* @author Dave Syer
* @since 1.0.0
*/
@SuppressWarnings("serial")
public class ClientSentEvent extends SpanContainingEvent {
public ClientSentEvent(Object source, Span span) {
super(source, span);
}
}
public interface SpanReporter {
/**
* Reports a completed span out of band, usually out of process.
* This is typically to a trace depot (ex zipkin) or a log file.
*/
void report(Span span);
}

View File

@@ -22,13 +22,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.SpanNamer;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.SpanLogger;
import org.springframework.cloud.sleuth.sampler.NeverSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -60,9 +62,10 @@ public class TraceAutoConfiguration {
@Bean
@ConditionalOnMissingBean(Tracer.class)
public DefaultTracer traceManager(Sampler sampler, Random random,
ApplicationEventPublisher publisher,
SpanNamer spanNamer) {
return new DefaultTracer(sampler, random, publisher, spanNamer);
SpanNamer spanNamer, SpanLogger spanLogger,
SpanReporter spanReporter) {
return new DefaultTracer(sampler, random, spanNamer, spanLogger,
spanReporter);
}
@Bean
@@ -77,4 +80,10 @@ public class TraceAutoConfiguration {
return new DefaultSpanNamer();
}
@Bean
@ConditionalOnMissingBean
public SpanReporter defaultSpanReporter() {
return new NoOpSpanReporter();
}
}

View File

@@ -1,38 +0,0 @@
/*
* 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.event;
import org.springframework.cloud.sleuth.Span;
/**
* <b>cr</b> - Client Receive. Signifies the end of the span. The client has successfully received the
* response from the server side. If one subtracts the cs timestamp from this timestamp one
* will receive the whole time needed by the client to receive the response from the server.
*
* @author Dave Syer
* @since 1.0.0
*
* @see ClientSentEvent
*/
@SuppressWarnings("serial")
public class ClientReceivedEvent extends SpanContainingEvent {
public ClientReceivedEvent(Object source, Span span) {
super(source, span);
}
}

View File

@@ -1,41 +0,0 @@
/*
* 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.event;
import org.springframework.cloud.sleuth.Span;
/**
* <b>ss</b> - Server Send. Annotated upon completion of request processing (when the response
* got sent back to the client). If one subtracts the sr timestamp from this timestamp one
* will receive the time needed by the server side to process the request.
*
* @author Spencer Gibb
* @since 1.0.0
*
* @see ServerReceivedEvent
*/
@SuppressWarnings("serial")
public class ServerSentEvent extends SpanParentContainingEvent {
public ServerSentEvent(Object source, Span span) {
this(source, null, span);
}
public ServerSentEvent(Object source, Span parent, Span span) {
super(source, parent, span);
}
}

View File

@@ -1,62 +0,0 @@
/*
* 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.event;
import java.util.Objects;
import org.springframework.cloud.sleuth.Span;
import org.springframework.context.ApplicationEvent;
/**
* @author Marcin Grzejszczak
*/
abstract class SpanContainingEvent extends ApplicationEvent {
private final Span span;
public SpanContainingEvent(Object source, Span span) {
super(source);
this.span = span;
}
public Span getSpan() {
return this.span;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SpanContainingEvent that = (SpanContainingEvent) o;
return Objects.equals(this.span, that.span);
}
@Override
public int hashCode() {
return this.span != null ? this.span.hashCode() : 0;
}
@Override
public String toString() {
return getClass().getSimpleName() + "{" +
"span=" + this.span +
'}';
}
}

View File

@@ -1,75 +0,0 @@
/*
* 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.event;
import java.util.Objects;
import org.springframework.cloud.sleuth.Span;
import org.springframework.context.ApplicationEvent;
/**
* @author Marcin Grzejszczak
*/
abstract class SpanParentContainingEvent extends ApplicationEvent {
private final Span span;
private final Span parent;
public SpanParentContainingEvent(Object source, Span span) {
this(source, null, span);
}
public SpanParentContainingEvent(Object source, Span parent, Span span) {
super(source);
this.parent = parent;
this.span = span;
}
public Span getParent() {
return this.parent;
}
public Span getSpan() {
return this.span;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SpanParentContainingEvent that = (SpanParentContainingEvent) o;
return Objects.equals(this.parent, that.parent) && Objects
.equals(this.span, that.span);
}
@Override
public int hashCode() {
return Objects.hash(this.parent, this.span);
}
@Override
public String toString() {
return getClass().getSimpleName() + "{" +
"span=" + this.span +
", parent=" + this.parent +
'}';
}
}

View File

@@ -1,37 +0,0 @@
/*
* 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.event;
import org.springframework.cloud.sleuth.Span;
/**
* Event emitted upon closing of a span. Results in preparing span for collection
* to external systems (logging, Zipkin etc.)
*
* @author Spencer Gibb
*/
@SuppressWarnings("serial")
public class SpanReleasedEvent extends SpanParentContainingEvent {
public SpanReleasedEvent(Object source, Span span) {
this(source, null, span);
}
public SpanReleasedEvent(Object source, Span parent, Span span) {
super(source, parent, span);
}
}

View File

@@ -29,14 +29,10 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Span.SpanBuilder;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ServerReceivedEvent;
import org.springframework.cloud.sleuth.event.ServerSentEvent;
import org.springframework.cloud.sleuth.sampler.NeverSampler;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.util.StringUtils;
@@ -68,8 +64,7 @@ import static org.springframework.util.StringUtils.hasText;
* @since 1.0.0
*/
@Order(Ordered.HIGHEST_PRECEDENCE + 5)
public class TraceFilter extends OncePerRequestFilter
implements ApplicationEventPublisherAware {
public class TraceFilter extends OncePerRequestFilter {
protected static final String TRACE_REQUEST_ATTR = TraceFilter.class.getName()
+ ".TRACE";
@@ -81,25 +76,22 @@ public class TraceFilter extends OncePerRequestFilter
private final TraceKeys traceKeys;
private final Pattern skipPattern;
private final Random random;
private final SpanReporter spanReporter;
private UrlPathHelper urlPathHelper = new UrlPathHelper();
private ApplicationEventPublisher publisher;
public TraceFilter(Tracer tracer, TraceKeys traceKeys) {
this(tracer, traceKeys, Pattern.compile(DEFAULT_SKIP_PATTERN), new Random());
public TraceFilter(Tracer tracer, TraceKeys traceKeys, SpanReporter spanReporter) {
this(tracer, traceKeys, Pattern.compile(DEFAULT_SKIP_PATTERN), new Random(),
spanReporter);
}
public TraceFilter(Tracer tracer, TraceKeys traceKeys, Pattern skipPattern,
Random random) {
Random random, SpanReporter spanReporter) {
this.tracer = tracer;
this.traceKeys = traceKeys;
this.skipPattern = skipPattern;
this.random = random;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
this.spanReporter = spanReporter;
}
@Override
@@ -152,7 +144,9 @@ public class TraceFilter extends OncePerRequestFilter
Span parent = span.build();
spanFromRequest = this.tracer.createSpan(name, parent);
publish(new ServerReceivedEvent(this, parent, spanFromRequest));
if (parent != null && parent.isRemote()) {
parent.logEvent(Span.SERVER_RECV);
}
request.setAttribute(TRACE_REQUEST_ATTR, spanFromRequest);
}
@@ -193,8 +187,11 @@ public class TraceFilter extends OncePerRequestFilter
if (spanFromRequest != null) {
addResponseTags(response, exception);
if (spanFromRequest.hasSavedSpan()) {
publish(new ServerSentEvent(this, spanFromRequest.getSavedSpan(),
spanFromRequest));
Span parent = spanFromRequest.getSavedSpan();
if (parent != null && parent.isRemote()) {
parent.logEvent(Span.SERVER_SEND);
this.spanReporter.report(parent);
}
}
// Double close to clean up the parent (remote span as well)
this.tracer.close(spanFromRequest);
@@ -211,12 +208,6 @@ public class TraceFilter extends OncePerRequestFilter
}
}
private void publish(ApplicationEvent event) {
if (this.publisher != null) {
this.publisher.publishEvent(event);
}
}
/** Override to add annotations not defined in {@link TraceKeys}. */
protected void addRequestTags(HttpServletRequest request) {
String uri = this.urlPathHelper.getPathWithinApplication(request);

View File

@@ -31,10 +31,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.sleuth.SpanAccessor;
import org.springframework.cloud.sleuth.SpanNamer;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
@@ -80,10 +80,10 @@ public class TraceWebAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public TraceFilter traceFilter(ApplicationEventPublisher publisher, Random random, SkipPatternProvider skipPatternProvider) {
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, skipPatternProvider.skipPattern(), random);
filter.setApplicationEventPublisher(publisher);
return filter;
public TraceFilter traceFilter(Random random,
SkipPatternProvider skipPatternProvider, SpanReporter spanReporter) {
return new TraceFilter(this.tracer, this.traceKeys, skipPatternProvider.skipPattern(), random,
spanReporter);
}
@Configuration

View File

@@ -20,11 +20,6 @@ import java.net.URI;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.http.HttpRequest;
import org.springframework.util.StringUtils;
@@ -36,20 +31,14 @@ import org.springframework.util.StringUtils;
*
* @since 1.0.0
*/
abstract class AbstractTraceHttpRequestInterceptor
implements ApplicationEventPublisherAware {
abstract class AbstractTraceHttpRequestInterceptor {
private ApplicationEventPublisher publisher;
protected final Tracer tracer;
protected AbstractTraceHttpRequestInterceptor(Tracer tracer) {
this.tracer = tracer;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
private void enrichWithTraceHeaders(HttpRequest request, Span span) {
setIdHeader(request, Span.TRACE_ID_NAME, span.getTraceId());
@@ -88,7 +77,7 @@ abstract class AbstractTraceHttpRequestInterceptor
String spanName = uriScheme(uri) + ":" + uri.getPath();
Span newSpan = this.tracer.createSpan(spanName);
enrichWithTraceHeaders(request, newSpan);
publish(new ClientSentEvent(this, newSpan));
newSpan.logEvent(Span.CLIENT_SEND);
}
private String uriScheme(URI uri) {
@@ -96,22 +85,16 @@ abstract class AbstractTraceHttpRequestInterceptor
}
/**
* Close the current span and emit the ClientReceivedEvent
* Close the current span and log the client received event
*/
public void finish() {
if (!isTracing()) {
return;
}
publish(new ClientReceivedEvent(this, currentSpan()));
currentSpan().logEvent(Span.CLIENT_RECV);
this.tracer.close(this.currentSpan());
}
private void publish(ApplicationEvent event) {
if (this.publisher != null) {
this.publisher.publishEvent(event);
}
}
protected Span currentSpan() {
return this.tracer.getCurrentSpan();
}

View File

@@ -20,10 +20,6 @@ import java.net.URI;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.AsyncClientHttpRequestFactory;
@@ -43,10 +39,7 @@ import org.springframework.web.client.RestTemplate;
*
* @since 1.0.0
*/
class TraceAsyncRestTemplate extends AsyncRestTemplate
implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
class TraceAsyncRestTemplate extends AsyncRestTemplate {
private final Tracer tracer;
@@ -93,16 +86,10 @@ class TraceAsyncRestTemplate extends AsyncRestTemplate
if (!isTracing()) {
return;
}
publish(new ClientReceivedEvent(this, currentSpan()));
currentSpan().logEvent(Span.CLIENT_RECV);
this.tracer.close(this.currentSpan());
}
private void publish(ApplicationEvent event) {
if (this.publisher != null) {
this.publisher.publishEvent(event);
}
}
private Span currentSpan() {
return this.tracer.getCurrentSpan();
}
@@ -111,9 +98,4 @@ class TraceAsyncRestTemplate extends AsyncRestTemplate
return this.tracer.isTracing();
}
@Override
public void setApplicationEventPublisher(
ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
}

View File

@@ -19,7 +19,6 @@ package org.springframework.cloud.sleuth.instrument.web.client.feign;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.context.ApplicationEventPublisher;
import feign.Client;
import feign.Retryer;
@@ -35,11 +34,9 @@ import feign.codec.Decoder;
*/
final class FeignBeanPostProcessor implements BeanPostProcessor {
private final ApplicationEventPublisher publisher;
private final Tracer tracer;
FeignBeanPostProcessor(ApplicationEventPublisher publisher, Tracer tracer) {
this.publisher = publisher;
FeignBeanPostProcessor(Tracer tracer) {
this.tracer = tracer;
}
@@ -47,11 +44,11 @@ final class FeignBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof Decoder && !(bean instanceof TraceFeignDecoder)) {
return new TraceFeignDecoder(this.publisher, this.tracer, (Decoder) bean);
return new TraceFeignDecoder(this.tracer, (Decoder) bean);
} else if (bean instanceof Retryer && !(bean instanceof TraceFeignRetryer)) {
return new TraceFeignRetryer(this.tracer, (Retryer) bean);
} else if (bean instanceof Client && !(bean instanceof TraceFeignClient)) {
return new TraceFeignClient(this.publisher, this.tracer, (Client) bean);
return new TraceFeignClient(this.tracer, (Client) bean);
}
return bean;
}

View File

@@ -18,11 +18,9 @@ package org.springframework.cloud.sleuth.instrument.web.client.feign;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.context.ApplicationEventPublisher;
/**
* Abstract class for publishing {@link org.springframework.cloud.sleuth.event.ClientReceivedEvent}
* Abstract class for publishing logging the client received event
*
* @author Marcin Grzejszczak
*
@@ -32,18 +30,16 @@ abstract class FeignEventPublisher {
private final FeignRequestContext feignRequestContext = FeignRequestContext.getInstance();
private final ApplicationEventPublisher publisher;
private final Tracer tracer;
protected FeignEventPublisher(ApplicationEventPublisher publisher, Tracer tracer) {
this.publisher = publisher;
protected FeignEventPublisher(Tracer tracer) {
this.tracer = tracer;
}
protected void finish() {
Span span = this.feignRequestContext.getCurrentSpan();
if (span != null) {
this.publisher.publishEvent(new ClientReceivedEvent(this, span));
span.logEvent(Span.CLIENT_RECV);
this.tracer.close(span);
this.feignRequestContext.clearContext();
}

View File

@@ -17,7 +17,6 @@
package org.springframework.cloud.sleuth.instrument.web.client.feign;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.context.ApplicationEventPublisher;
import feign.Feign;
import feign.hystrix.HystrixFeign;
@@ -35,10 +34,10 @@ final class SleuthFeignBuilder {
private SleuthFeignBuilder() {}
static Feign.Builder builder(ApplicationEventPublisher publisher, Tracer tracer) {
static Feign.Builder builder(Tracer tracer) {
return HystrixFeign.builder()
.client(new TraceFeignClient(publisher, tracer))
.client(new TraceFeignClient(tracer))
.retryer(new TraceFeignRetryer(tracer))
.decoder(new TraceFeignDecoder(publisher, tracer));
.decoder(new TraceFeignDecoder(tracer));
}
}

View File

@@ -20,7 +20,6 @@ import java.io.IOException;
import java.util.Objects;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.context.ApplicationEventPublisher;
import feign.Client;
import feign.Request;
@@ -38,13 +37,13 @@ final class TraceFeignClient extends FeignEventPublisher implements Client {
private final Client delegate;
TraceFeignClient(ApplicationEventPublisher publisher, Tracer tracer) {
super(publisher, tracer);
TraceFeignClient(Tracer tracer) {
super(tracer);
this.delegate = new Client.Default(null, null);
}
TraceFeignClient(ApplicationEventPublisher publisher, Tracer tracer, Client delegate) {
super(publisher, tracer);
TraceFeignClient(Tracer tracer, Client delegate) {
super(tracer);
this.delegate = delegate;
}

View File

@@ -36,7 +36,6 @@ import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixAutoConfiguration;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@@ -72,9 +71,6 @@ public class TraceFeignClientAutoConfiguration {
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Autowired
private ApplicationEventPublisher publisher;
@Autowired
private Tracer tracer;
@@ -85,19 +81,19 @@ public class TraceFeignClientAutoConfiguration {
@ConditionalOnClass(HystrixCommand.class)
@ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = true)
public Feign.Builder feignHystrixBuilder(Tracer tracer, TraceKeys traceKeys) {
return SleuthFeignBuilder.builder(this.publisher, tracer);
return SleuthFeignBuilder.builder(tracer);
}
@Bean
@ConditionalOnProperty(name = "spring.sleuth.feign.processor.enabled", matchIfMissing = true)
public FeignBeanPostProcessor feignBeanPostProcessor(Tracer tracer) {
return new FeignBeanPostProcessor(this.publisher, tracer);
return new FeignBeanPostProcessor(tracer);
}
@Bean
@Primary
public Decoder feignDecoder(final Tracer tracer) {
return new TraceFeignDecoder(this.publisher, tracer, new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)) {
return new TraceFeignDecoder(tracer, new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)) {
@Override
public Object decode(Response response, Type type)
throws IOException, FeignException {

View File

@@ -20,7 +20,6 @@ import java.io.IOException;
import java.lang.reflect.Type;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.context.ApplicationEventPublisher;
import feign.FeignException;
import feign.Response;
@@ -38,13 +37,13 @@ final class TraceFeignDecoder extends FeignEventPublisher implements Decoder {
private final Decoder delegate;
TraceFeignDecoder(ApplicationEventPublisher publisher, Tracer tracer) {
super(publisher, tracer);
TraceFeignDecoder(Tracer tracer) {
super(tracer);
this.delegate = new Decoder.Default();
}
TraceFeignDecoder(ApplicationEventPublisher publisher, Tracer tracer, Decoder delegate) {
super(publisher, tracer);
TraceFeignDecoder(Tracer tracer, Decoder delegate) {
super(tracer);
this.delegate = delegate;
}

View File

@@ -20,10 +20,6 @@ import java.net.URI;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.util.StringUtils;
import feign.RequestInterceptor;
@@ -37,14 +33,11 @@ import feign.RequestTemplate;
*
* @since 1.0.0
*/
final class TraceFeignRequestInterceptor implements RequestInterceptor,
ApplicationEventPublisherAware {
final class TraceFeignRequestInterceptor implements RequestInterceptor {
private final Tracer tracer;
private final FeignRequestContext feignRequestContext = FeignRequestContext.getInstance();
private ApplicationEventPublisher publisher;
TraceFeignRequestInterceptor(Tracer tracer) {
this.tracer = tracer;
}
@@ -68,7 +61,7 @@ final class TraceFeignRequestInterceptor implements RequestInterceptor,
setHeader(template, Span.PARENT_ID_NAME, Span.idToHex(parentId));
}
setHeader(template, Span.PROCESS_ID_NAME, span.getProcessId());
publish(new ClientSentEvent(this, span));
span.logEvent(Span.CLIENT_SEND);
}
protected String getSpanName(RequestTemplate template) {
@@ -108,15 +101,4 @@ final class TraceFeignRequestInterceptor implements RequestInterceptor,
}
}
private void publish(ApplicationEvent event) {
if (this.publisher != null) {
this.publisher.publishEvent(event);
}
}
@Override
public void setApplicationEventPublisher(
ApplicationEventPublisher applicationEventPublisher) {
this.publisher = applicationEventPublisher;
}
}

View File

@@ -18,10 +18,6 @@ package org.springframework.cloud.sleuth.instrument.zuul;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanAccessor;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import com.netflix.zuul.ZuulFilter;
@@ -32,20 +28,12 @@ import com.netflix.zuul.ZuulFilter;
*
* @since 1.0.0
*/
public class TracePostZuulFilter extends ZuulFilter
implements ApplicationEventPublisherAware {
public class TracePostZuulFilter extends ZuulFilter {
private ApplicationEventPublisher publisher;
private final SpanAccessor spanAccessor;
private final SpanAccessor accessor;
public TracePostZuulFilter(SpanAccessor accessor) {
this.accessor = accessor;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
public TracePostZuulFilter(SpanAccessor spanAccessor) {
this.spanAccessor = spanAccessor;
}
@Override
@@ -56,7 +44,7 @@ public class TracePostZuulFilter extends ZuulFilter
@Override
public Object run() {
// TODO: the client sent event should come from the client not the filter!
publish(new ClientReceivedEvent(this, getCurrentSpan()));
getCurrentSpan().logEvent(Span.CLIENT_RECV);
return null;
}
@@ -70,13 +58,7 @@ public class TracePostZuulFilter extends ZuulFilter
return 0;
}
private void publish(ApplicationEvent event) {
if (this.publisher != null) {
this.publisher.publishEvent(event);
}
}
private Span getCurrentSpan() {
return this.accessor.getCurrentSpan();
return this.spanAccessor.getCurrentSpan();
}
}

View File

@@ -20,10 +20,6 @@ import java.util.Map;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanAccessor;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
@@ -38,10 +34,7 @@ import com.netflix.zuul.context.RequestContext;
*
* @since 1.0.0
*/
public class TracePreZuulFilter extends ZuulFilter
implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
public class TracePreZuulFilter extends ZuulFilter {
private final SpanAccessor accessor;
@@ -49,11 +42,6 @@ public class TracePreZuulFilter extends ZuulFilter
this.accessor = accessor;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@Override
public boolean shouldFilter() {
return true;
@@ -78,7 +66,7 @@ public class TracePreZuulFilter extends ZuulFilter
setHeader(requestHeaders, Span.PARENT_ID_NAME, getParentId(span));
setHeader(requestHeaders, Span.PROCESS_ID_NAME, span.getProcessId());
// TODO: the client sent event should come from the client not the filter!
publish(new ClientSentEvent(this, span));
span.logEvent(Span.CLIENT_SEND);
}
catch (Exception ex) {
ReflectionUtils.rethrowRuntimeException(ex);
@@ -116,10 +104,4 @@ public class TracePreZuulFilter extends ZuulFilter
return 0;
}
private void publish(ApplicationEvent event) {
if (this.publisher != null) {
this.publisher.publishEvent(event);
}
}
}

View File

@@ -27,10 +27,6 @@ import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonComm
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanAccessor;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.util.MultiValueMap;
import com.netflix.client.http.HttpRequest;
@@ -43,13 +39,10 @@ import com.netflix.niws.client.http.RestClient;
*
* @since 1.0.0
*/
public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommandFactory
implements ApplicationEventPublisherAware {
public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommandFactory {
private static final Log log = LogFactory.getLog(TraceRestClientRibbonCommandFactory.class);
private ApplicationEventPublisher publisher;
private final SpanAccessor accessor;
public TraceRestClientRibbonCommandFactory(SpringClientFactory clientFactory,
@@ -58,11 +51,6 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
this.accessor = accessor;
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@Override
@SuppressWarnings("deprecation")
public RestClientRibbonCommand create(RibbonCommandContext context) {
@@ -72,7 +60,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.publisher, this.accessor);
this.accessor);
}
catch (URISyntaxException e) {
log.error("Exception occurred while trying to create the TraceRestClientRibbonCommand", e);
@@ -82,8 +70,6 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
class TraceRestClientRibbonCommand extends RestClientRibbonCommand {
private ApplicationEventPublisher publisher;
private final SpanAccessor accessor;
@SuppressWarnings("deprecation")
@@ -91,11 +77,10 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
HttpRequest.Verb verb, String uri, Boolean retryable,
MultiValueMap<String, String> headers,
MultiValueMap<String, String> params, InputStream requestEntity,
ApplicationEventPublisher publisher, SpanAccessor accessor)
SpanAccessor accessor)
throws URISyntaxException {
super(commandKey, restClient, verb, uri, retryable, headers, params,
requestEntity);
this.publisher = publisher;
this.accessor = accessor;
}
@@ -115,13 +100,7 @@ public class TraceRestClientRibbonCommandFactory extends RestClientRibbonCommand
}
setHeader(requestBuilder, Span.PROCESS_ID_NAME,
span.getProcessId());
publish(new ClientSentEvent(this, span));
}
private void publish(ApplicationEvent event) {
if (this.publisher != null) {
this.publisher.publishEvent(event);
}
span.logEvent(Span.CLIENT_SEND);
}
private Long getParentId(Span span) {

View File

@@ -14,24 +14,30 @@
* limitations under the License.
*/
package org.springframework.cloud.sleuth.event;
package org.springframework.cloud.sleuth.log;
import org.springframework.cloud.sleuth.Span;
/**
* Event emitted when a parent or a child span was created.
* Logger of Spans that does nothing
*
* @author Marcin Grzejszczak
*
* @author Spencer Gibb
* @since 1.0.0
*/
@SuppressWarnings("serial")
public class SpanAcquiredEvent extends SpanParentContainingEvent {
public class NoOpSpanLogger implements SpanLogger {
@Override
public void logStartedSpan(Span parent, Span span) {
public SpanAcquiredEvent(Object source, Span span) {
this(source, null, span);
}
public SpanAcquiredEvent(Object source, Span parent, Span span) {
super(source, parent, span);
@Override
public void logContinuedSpan(Span span) {
}
}
@Override
public void logStoppedSpan(Span parent, Span span) {
}
}

View File

@@ -21,6 +21,8 @@ import org.springframework.beans.factory.annotation.Value;
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.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
@@ -29,7 +31,7 @@ import org.springframework.context.annotation.Configuration;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
* enables a {@link Slf4jSpanListener} that prints tracing information in the logs.
* enables a {@link Slf4jSpanLogger} that prints tracing information in the logs.
* <p>
* Note: this is only available for Slf4j
*
@@ -53,9 +55,22 @@ public class SleuthLogAutoConfiguration {
@Bean
@ConditionalOnProperty(value = "spring.sleuth.log.slf4j.enabled", matchIfMissing = true)
public Slf4jSpanListener slf4jSpanStartedListener() {
public SpanLogger slf4jSpanLogger() {
// Sets up MDC entries X-Trace-Id and X-Span-Id
return new Slf4jSpanListener(this.nameSkipPattern);
return new Slf4jSpanLogger(this.nameSkipPattern);
}
@Bean
@ConditionalOnProperty(value = "spring.sleuth.log.slf4j.enabled", havingValue = "false")
public SpanLogger noOpSlf4jSpanLogger() {
return new NoOpSpanLogger();
}
}
@Bean
@ConditionalOnMissingClass("org.slf4j.MDC")
@ConditionalOnMissingBean
public SpanLogger defaultLoggedSpansHandler() {
return new NoOpSpanLogger();
}
}

View File

@@ -21,12 +21,6 @@ import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.MDC;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.event.SpanAcquiredEvent;
import org.springframework.cloud.sleuth.event.SpanContinuedEvent;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
/**
* Span listener that logs to the console when a span got
@@ -36,53 +30,48 @@ import org.springframework.core.annotation.Order;
*
* @since 1.0.0
*/
public class Slf4jSpanListener {
public class Slf4jSpanLogger implements SpanLogger {
private final Logger log;
private final Pattern nameSkipPattern;
public Slf4jSpanListener(String nameSkipPattern) {
public Slf4jSpanLogger(String nameSkipPattern) {
this.nameSkipPattern = Pattern.compile(nameSkipPattern);
this.log = org.slf4j.LoggerFactory
.getLogger(Slf4jSpanListener.class);
.getLogger(Slf4jSpanLogger.class);
}
Slf4jSpanListener(String nameSkipPattern, Logger log) {
Slf4jSpanLogger(String nameSkipPattern, Logger log) {
this.nameSkipPattern = Pattern.compile(nameSkipPattern);
this.log = log;
}
@EventListener(SpanAcquiredEvent.class)
@Order(Ordered.LOWEST_PRECEDENCE)
public void start(SpanAcquiredEvent event) {
Span span = event.getSpan();
@Override
public void logStartedSpan(Span parent, Span span) {
MDC.put(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
MDC.put(Span.SPAN_EXPORT_NAME, String.valueOf(span.isExportable()));
MDC.put(Span.TRACE_ID_NAME, Span.idToHex(span.getTraceId()));
log("Starting span: {}", span);
if (event.getParent() != null) {
log("With parent: {}", event.getParent());
if (parent != null) {
log("With parent: {}", parent);
}
}
@EventListener(SpanContinuedEvent.class)
@Order(Ordered.LOWEST_PRECEDENCE)
public void continued(SpanContinuedEvent event) {
Span span = event.getSpan();
@Override
public void logContinuedSpan(Span span) {
MDC.put(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
MDC.put(Span.TRACE_ID_NAME, Span.idToHex(span.getTraceId()));
MDC.put(Span.SPAN_EXPORT_NAME, String.valueOf(span.isExportable()));
log("Continued span: {}", event.getSpan());
log("Continued span: {}", span);
}
@EventListener(SpanReleasedEvent.class)
@Order(Ordered.LOWEST_PRECEDENCE)
public void stop(SpanReleasedEvent event) {
log("Stopped span: {}", event.getSpan());
if (event.getParent() != null) {
log("With parent: {}", event.getParent());
MDC.put(Span.SPAN_ID_NAME, Span.idToHex(event.getParent().getSpanId()));
MDC.put(Span.SPAN_EXPORT_NAME, String.valueOf(event.getParent().isExportable()));
@Override
public void logStoppedSpan(Span parent, Span span) {
log("Stopped span: {}", span);
if (parent != null) {
log("With parent: {}", parent);
MDC.put(Span.SPAN_ID_NAME, Span.idToHex(parent.getSpanId()));
MDC.put(Span.SPAN_EXPORT_NAME, String.valueOf(parent.isExportable()));
}
else {
MDC.remove(Span.SPAN_ID_NAME);

View File

@@ -14,27 +14,37 @@
* limitations under the License.
*/
package org.springframework.cloud.sleuth.event;
package org.springframework.cloud.sleuth.log;
import org.springframework.cloud.sleuth.Span;
/**
* <b>sr</b> - Server Receive. The server side got the request and will start processing it.
* If one subtracts the cs timestamp from this timestamp one will receive the network latency.
* Contract for implementations responsible for logging Spans
*
* @author Marcin Grzejszczak
*
* @author Spencer Gibb
* @since 1.0.0
*
* @see ClientSentEvent
*/
@SuppressWarnings("serial")
public class ServerReceivedEvent extends SpanParentContainingEvent {
public interface SpanLogger {
public ServerReceivedEvent(Object source, Span span) {
this(source, null, span);
}
/**
* Logic to run when a Span gets started
*
* @param parent - maybe be nullable
* @param span - current span
*/
void logStartedSpan(Span parent, Span span);
public ServerReceivedEvent(Object source, Span parent, Span span) {
super(source, parent, span);
}
/**
* Logic to run when a Span gets continued
*/
void logContinuedSpan(Span span);
/**
* Logic to run when a Span gets stopped (closed or detached)
*
* @param parent - maybe be nullable
* @param span - current span
*/
void logStoppedSpan(Span parent, Span span);
}

View File

@@ -10,12 +10,12 @@ import org.springframework.boot.actuate.metrics.CounterService;
*
* @since 1.0.0
*/
public class CounterServiceBasedSpanReporterService implements SpanReporterService {
public class CounterServiceBasedSpanMetricReporter implements SpanMetricReporter {
private final String acceptedSpansMetricName;
private final String droppedSpansMetricName;
private final CounterService counterService;
public CounterServiceBasedSpanReporterService(String acceptedSpansMetricName,
public CounterServiceBasedSpanMetricReporter(String acceptedSpansMetricName,
String droppedSpansMetricName, CounterService counterService) {
this.acceptedSpansMetricName = acceptedSpansMetricName;
this.droppedSpansMetricName = droppedSpansMetricName;

View File

@@ -1,13 +1,13 @@
package org.springframework.cloud.sleuth.metric;
/**
* {@link SpanReporterService} that does nothing
* {@link SpanMetricReporter} that does nothing
*
* @author Marcin Grzejszczak
*
* @since 1.0.0
*/
public class NoOpSpanReporterService implements SpanReporterService {
public class NoOpSpanMetricReporter implements SpanMetricReporter {
public void incrementAcceptedSpans(long quantity) {

View File

@@ -7,7 +7,7 @@ package org.springframework.cloud.sleuth.metric;
*
* @since 1.0.0
*/
public interface SpanReporterService {
public interface SpanMetricReporter {
/**
* Called when spans are submitted to span collector for processing.

View File

@@ -47,27 +47,27 @@ public class TraceMetricsAutoConfiguration {
@Configuration
@ConditionalOnClass(CounterService.class)
@ConditionalOnMissingBean(SpanReporterService.class)
@ConditionalOnMissingBean(SpanMetricReporter.class)
protected static class CounterServiceSpanReporterConfig {
@Bean
@ConditionalOnBean(CounterService.class)
public SpanReporterService spanReporterCounterService(CounterService counterService,
public SpanMetricReporter spanReporterCounterService(CounterService counterService,
SleuthMetricProperties sleuthMetricProperties) {
return new CounterServiceBasedSpanReporterService(sleuthMetricProperties.getSpan().getAcceptedName(),
return new CounterServiceBasedSpanMetricReporter(sleuthMetricProperties.getSpan().getAcceptedName(),
sleuthMetricProperties.getSpan().getDroppedName(), counterService);
}
@Bean
@ConditionalOnMissingBean(CounterService.class)
public SpanReporterService noOpSpanReporterCounterService() {
return new NoOpSpanReporterService();
public SpanMetricReporter noOpSpanReporterCounterService() {
return new NoOpSpanMetricReporter();
}
}
@Bean
@ConditionalOnMissingClass("org.springframework.boot.actuate.metrics.CounterService")
@ConditionalOnMissingBean(SpanReporterService.class)
public SpanReporterService noOpSpanReporterCounterService() {
return new NoOpSpanReporterService();
@ConditionalOnMissingBean(SpanMetricReporter.class)
public SpanMetricReporter noOpSpanReporterCounterService() {
return new NoOpSpanMetricReporter();
}
}

View File

@@ -22,14 +22,12 @@ import java.util.concurrent.Callable;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanNamer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.SpanAcquiredEvent;
import org.springframework.cloud.sleuth.event.SpanContinuedEvent;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.cloud.sleuth.TraceCallable;
import org.springframework.cloud.sleuth.TraceRunnable;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.SpanLogger;
import org.springframework.cloud.sleuth.util.ExceptionUtils;
import org.springframework.context.ApplicationEventPublisher;
/**
* Default implementation of {@link Tracer}
@@ -42,18 +40,22 @@ public class DefaultTracer implements Tracer {
private final Sampler defaultSampler;
private final ApplicationEventPublisher publisher;
private final Random random;
private final SpanNamer spanNamer;
private final SpanLogger spanLogger;
private final SpanReporter spanReporter;
public DefaultTracer(Sampler defaultSampler, Random random,
ApplicationEventPublisher publisher, SpanNamer spanNamer) {
SpanNamer spanNamer, SpanLogger spanLogger,
SpanReporter spanReporter) {
this.defaultSampler = defaultSampler;
this.random = random;
this.publisher = publisher;
this.spanNamer = spanNamer;
this.spanLogger = spanLogger;
this.spanReporter = spanReporter;
}
@Override
@@ -87,7 +89,7 @@ public class DefaultTracer implements Tracer {
span = Span.builder().begin(span.getBegin()).name(name).traceId(id)
.spanId(id).exportable(false).build();
}
this.publisher.publishEvent(new SpanAcquiredEvent(this, span));
this.spanLogger.logStartedSpan(null, span);
}
return continueSpan(span);
}
@@ -124,11 +126,13 @@ public class DefaultTracer implements Tracer {
else {
span.stop();
if (savedSpan != null && span.getParents().contains(savedSpan.getSpanId())) {
this.publisher.publishEvent(new SpanReleasedEvent(this, savedSpan, span));
this.spanReporter.report(span);
this.spanLogger.logStoppedSpan(savedSpan, span);
}
else {
if (!span.isRemote()) {
this.publisher.publishEvent(new SpanReleasedEvent(this, span));
this.spanReporter.report(span);
this.spanLogger.logStoppedSpan(null, span);
}
}
SpanContextHolder.close();
@@ -141,7 +145,7 @@ public class DefaultTracer implements Tracer {
if (parent == null) {
Span span = Span.builder().begin(System.currentTimeMillis()).name(name)
.traceId(id).spanId(id).build();
this.publisher.publishEvent(new SpanAcquiredEvent(this, span));
this.spanLogger.logStartedSpan(null, span);
return span;
}
else {
@@ -152,7 +156,7 @@ public class DefaultTracer implements Tracer {
.traceId(parent.getTraceId()).parent(parent.getSpanId()).spanId(id)
.processId(parent.getProcessId()).savedSpan(parent)
.exportable(parent.isExportable()).build();
this.publisher.publishEvent(new SpanAcquiredEvent(this, parent, span));
this.spanLogger.logStartedSpan(parent, span);
return span;
}
}
@@ -164,7 +168,7 @@ public class DefaultTracer implements Tracer {
@Override
public Span continueSpan(Span span) {
if (span != null) {
this.publisher.publishEvent(new SpanContinuedEvent(this, span));
this.spanLogger.logContinuedSpan(span);
} else {
return null;
}

View File

@@ -14,13 +14,13 @@
* limitations under the License.
*/
package org.springframework.cloud.sleuth.event;
package org.springframework.cloud.sleuth.util;
import java.util.ArrayList;
import java.util.List;
import org.springframework.cloud.sleuth.Span;
import org.springframework.context.ApplicationListener;
import org.springframework.cloud.sleuth.SpanReporter;
/**
* Accumulator of {@link org.springframework.cloud.sleuth.Tracer#close(Span)
@@ -29,14 +29,9 @@ import org.springframework.context.ApplicationListener;
* @author Spencer Gibb
* @since 1.0.0
*/
public class ArrayListSpanAccumulator implements ApplicationListener<SpanReleasedEvent> {
public class ArrayListSpanAccumulator implements SpanReporter {
private final List<Span> spans = new ArrayList<>();
@Override
public void onApplicationEvent(SpanReleasedEvent event) {
this.spans.add(event.getSpan());
}
public List<Span> getSpans() {
return this.spans;
}
@@ -47,4 +42,9 @@ public class ArrayListSpanAccumulator implements ApplicationListener<SpanRelease
"spans=" + this.spans +
'}';
}
@Override
public void report(Span span) {
this.spans.add(span);
}
}

View File

@@ -27,6 +27,7 @@ import org.junit.Test;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanName;
@@ -34,9 +35,9 @@ import org.springframework.cloud.sleuth.SpanNamer;
import org.springframework.cloud.sleuth.TraceCallable;
import org.springframework.cloud.sleuth.TraceRunnable;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -115,8 +116,8 @@ public class SpringCloudSleuthDocTests {
executorService.shutdown();
}
ApplicationEventPublisher publisher = Mockito.mock(ApplicationEventPublisher.class);
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher, new DefaultSpanNamer());
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), new DefaultSpanNamer(),
new NoOpSpanLogger(), new NoOpSpanReporter());
@Test
public void should_create_a_span_with_tracer() {
@@ -222,7 +223,8 @@ public class SpringCloudSleuthDocTests {
@Test
public void should_wrap_runnable_in_its_sleuth_representative() {
SpanNamer spanNamer = new DefaultSpanNamer();
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher, spanNamer);
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), spanNamer,
new NoOpSpanLogger(), new NoOpSpanReporter());
Span initialSpan = tracer.createSpan("initialSpan");
// tag::trace_runnable[]
Runnable runnable = new Runnable() {
@@ -251,7 +253,8 @@ public class SpringCloudSleuthDocTests {
@Test
public void should_wrap_callable_in_its_sleuth_representative() {
SpanNamer spanNamer = new DefaultSpanNamer();
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher, spanNamer);
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), spanNamer,
new NoOpSpanLogger(), new NoOpSpanReporter());
Span initialSpan = tracer.createSpan("initialSpan");
// tag::trace_callable[]
Callable<String> callable = new Callable<String>() {

View File

@@ -8,17 +8,17 @@ import java.util.concurrent.Executors;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanName;
import org.springframework.cloud.sleuth.TraceCallable;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
@@ -27,7 +27,8 @@ public class TraceCallableTests {
ExecutorService executor = Executors.newSingleThreadExecutor();
Tracer tracer = new DefaultTracer(new AlwaysSampler(),
new Random(), Mockito.mock(ApplicationEventPublisher.class), new DefaultSpanNamer());
new Random(), new DefaultSpanNamer(),
new NoOpSpanLogger(), new NoOpSpanReporter());
@After
public void clean() {

View File

@@ -8,17 +8,17 @@ import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanName;
import org.springframework.cloud.sleuth.TraceRunnable;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
@@ -27,7 +27,8 @@ public class TraceRunnableTests {
ExecutorService executor = Executors.newSingleThreadExecutor();
Tracer tracer = new DefaultTracer(new AlwaysSampler(),
new Random(), Mockito.mock(ApplicationEventPublisher.class), new DefaultSpanNamer());
new Random(), new DefaultSpanNamer(),
new NoOpSpanLogger(), new NoOpSpanReporter());
@After
public void cleanup() {

View File

@@ -15,14 +15,15 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanNamer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.BDDAssertions.then;
@@ -31,7 +32,6 @@ import static org.assertj.core.api.BDDAssertions.then;
public class TraceableExecutorServiceTests {
private static int TOTAL_THREADS = 10;
@Mock ApplicationEventPublisher publisher;
@Mock SpanNamer spanNamer;
Tracer tracer;
ExecutorService executorService = Executors.newFixedThreadPool(3);
@@ -40,8 +40,8 @@ public class TraceableExecutorServiceTests {
@Before
public void setup() {
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher,
this.spanNamer);
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.spanNamer, new NoOpSpanLogger(), new NoOpSpanReporter());
this.traceManagerableExecutorService = new TraceableExecutorService(this.executorService,
this.tracer, new TraceKeys(), this.spanNamer);
TestSpanContextHolder.removeCurrentSpan();

View File

@@ -5,15 +5,15 @@ import java.util.Random;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
@@ -31,7 +31,7 @@ public class TraceCommandTests {
static final long EXPECTED_TRACE_ID = 1L;
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
Mockito.mock(ApplicationEventPublisher.class), new DefaultSpanNamer());
new DefaultSpanNamer(), new NoOpSpanLogger(), new NoOpSpanReporter());
@Before
public void setup() {
@@ -85,7 +85,7 @@ public class TraceCommandTests {
@Test
public void should_pass_tracing_information_when_using_Hystrix_commands() {
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
Mockito.mock(ApplicationEventPublisher.class), new DefaultSpanNamer());
new DefaultSpanNamer(), new NoOpSpanLogger(), new NoOpSpanReporter());
TraceKeys traceKeys = new TraceKeys();
HystrixCommand.Setter setter = HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey("group"))

View File

@@ -16,9 +16,6 @@
package org.springframework.cloud.sleuth.instrument.messaging;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -30,13 +27,12 @@ import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import org.springframework.cloud.sleuth.util.ArrayListSpanAccumulator;
import org.springframework.cloud.sleuth.instrument.messaging.TraceChannelInterceptorTests.App;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.support.MessageBuilder;
@@ -72,7 +68,7 @@ public class TraceChannelInterceptorTests implements MessageHandler {
private MessagingTemplate messagingTemplate;
@Autowired
private App app;
private ArrayListSpanAccumulator accumulator;
private Message<?> message;
@@ -120,7 +116,7 @@ public class TraceChannelInterceptorTests implements MessageHandler {
.hexToId(this.message.getHeaders().get(Span.TRACE_ID_NAME, String.class));
then(traceId).isEqualTo(10L);
then(spanId).isNotEqualTo(20L);
assertEquals(1, this.app.events.size());
assertEquals(1, this.accumulator.getSpans().size());
}
@Test
@@ -171,11 +167,9 @@ public class TraceChannelInterceptorTests implements MessageHandler {
@EnableAutoConfiguration
static class App {
private List<SpanReleasedEvent> events = new ArrayList<>();
@EventListener
public void handle(SpanReleasedEvent event) {
this.events.add(event);
@Bean
ArrayListSpanAccumulator arrayListSpanAccumulator() {
return new ArrayListSpanAccumulator();
}
@Bean

View File

@@ -10,6 +10,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration;
@@ -74,7 +75,8 @@ public class TraceFilterAlwaysSamplerIntegrationTests extends AbstractMvcIntegra
@Override
protected void configureMockMvcBuilder(DefaultMockMvcBuilder mockMvcBuilder) {
mockMvcBuilder.addFilters(new TraceFilter(this.tracer, this.traceKeys));
mockMvcBuilder.addFilters(new TraceFilter(this.tracer, this.traceKeys,
new NoOpSpanReporter()));
}
private MvcResult whenSentPingWithTraceIdAndNotSampling(Long traceId)

View File

@@ -21,13 +21,14 @@ import java.util.Random;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
@@ -44,10 +45,9 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
*/
public class TraceFilterMockChainIntegrationTests {
private StaticApplicationContext context = new StaticApplicationContext();
private Tracer tracer = new DefaultTracer(new AlwaysSampler(),
new Random(), this.context, new DefaultSpanNamer());
new Random(), new DefaultSpanNamer(),
new NoOpSpanLogger(), new NoOpSpanReporter());
private TraceKeys traceKeys = new TraceKeys();
private MockHttpServletRequest request;
@@ -57,7 +57,6 @@ public class TraceFilterMockChainIntegrationTests {
@Before
public void init() {
TestSpanContextHolder.removeCurrentSpan();
this.context.refresh();
this.request = builder().buildRequest(new MockServletContext());
this.response = new MockHttpServletResponse();
this.response.setContentType(MediaType.APPLICATION_JSON_VALUE);
@@ -71,7 +70,7 @@ public class TraceFilterMockChainIntegrationTests {
@Test
public void startsNewTrace() throws Exception {
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, new NoOpSpanReporter());
filter.doFilter(this.request, this.response, this.filterChain);
assertNull(TestSpanContextHolder.getCurrentSpan());
}
@@ -81,7 +80,7 @@ public class TraceFilterMockChainIntegrationTests {
Random generator = new Random();
this.request = builder().header(Span.SPAN_ID_NAME, generator.nextLong())
.header(Span.TRACE_ID_NAME, generator.nextLong()).buildRequest(new MockServletContext());
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, new NoOpSpanReporter());
filter.doFilter(this.request, this.response, this.filterChain);
assertNull(TestSpanContextHolder.getCurrentSpan());
}

View File

@@ -24,13 +24,14 @@ import org.mockito.Mock;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
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.TraceKeys;
import org.springframework.cloud.sleuth.log.SpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.sampler.NeverSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockFilterChain;
@@ -52,8 +53,8 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder
*/
public class TraceFilterTests {
@Mock
private ApplicationEventPublisher publisher;
@Mock SpanLogger spanLogger;
@Mock SpanReporter spanReporter;
private Tracer tracer;
private TraceKeys traceKeys = new TraceKeys();
@@ -69,7 +70,7 @@ public class TraceFilterTests {
public void init() {
initMocks(this);
this.tracer = new DefaultTracer(new DelegateSampler(), new Random(),
this.publisher, new DefaultSpanNamer()) {
new DefaultSpanNamer(), this.spanLogger, this.spanReporter) {
@Override
public Span continueSpan(Span span) {
TraceFilterTests.this.span = super.continueSpan(span);
@@ -90,7 +91,7 @@ public class TraceFilterTests {
@Test
public void notTraced() throws Exception {
this.sampler = NeverSampler.INSTANCE;
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, spanReporter);
this.request = get("/favicon.ico").accept(MediaType.ALL)
.buildRequest(new MockServletContext());
@@ -103,7 +104,7 @@ public class TraceFilterTests {
@Test
public void startsNewTrace() throws Exception {
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, spanReporter);
filter.doFilter(this.request, this.response, this.filterChain);
verifyHttpTags();
assertNull(TestSpanContextHolder.getCurrentSpan());
@@ -116,7 +117,7 @@ public class TraceFilterTests {
.header(Span.TRACE_ID_NAME, Span.idToHex(2L))
.header(Span.PARENT_ID_NAME, Span.idToHex(3L))
.buildRequest(new MockServletContext());
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, spanReporter);
filter.doFilter(this.request, this.response, this.filterChain);
@@ -132,7 +133,7 @@ public class TraceFilterTests {
// It should have been removed from the thread local context so simulate that
TestSpanContextHolder.removeCurrentSpan();
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, spanReporter);
filter.doFilter(this.request, this.response, this.filterChain);
verifyHttpTags();
@@ -145,7 +146,7 @@ public class TraceFilterTests {
this.request = builder().header(Span.SPAN_ID_NAME, 10L)
.header(Span.TRACE_ID_NAME, 20L).buildRequest(new MockServletContext());
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, spanReporter);
filter.doFilter(this.request, this.response, this.filterChain);
verifyHttpTags();
@@ -159,7 +160,7 @@ public class TraceFilterTests {
.header(Span.TRACE_ID_NAME, 20L).buildRequest(new MockServletContext());
this.traceKeys.getHttp().getHeaders().add("x-foo");
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, spanReporter);
this.request.addHeader("X-Foo", "bar");
filter.doFilter(this.request, this.response, this.filterChain);
@@ -174,7 +175,7 @@ public class TraceFilterTests {
.header(Span.TRACE_ID_NAME, 20L).buildRequest(new MockServletContext());
this.traceKeys.getHttp().getHeaders().add("x-foo");
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, spanReporter);
this.request.addHeader("X-Foo", "bar");
this.request.addHeader("X-Foo", "spam");
filter.doFilter(this.request, this.response, this.filterChain);
@@ -186,7 +187,7 @@ public class TraceFilterTests {
@Test
public void catchesException() throws Exception {
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys);
TraceFilter filter = new TraceFilter(this.tracer, this.traceKeys, spanReporter);
this.filterChain = new MockFilterChain() {
@Override
public void doFilter(javax.servlet.ServletRequest request,

View File

@@ -22,12 +22,13 @@ import java.util.concurrent.Callable;
import org.junit.Test;
import org.mockito.BDDMockito;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.TraceCallable;
import org.springframework.cloud.sleuth.TraceRunnable;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.core.task.AsyncListenableTaskExecutor;
import static org.hamcrest.Matchers.instanceOf;
@@ -39,9 +40,8 @@ import static org.mockito.BDDMockito.mock;
public class TraceAsyncListenableTaskExecutorTest {
AsyncListenableTaskExecutor delegate = mock(AsyncListenableTaskExecutor.class);
ApplicationEventPublisher publisher = mock(ApplicationEventPublisher.class);
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.publisher, new DefaultSpanNamer()) {
new DefaultSpanNamer(), new NoOpSpanLogger(), new NoOpSpanReporter()) {
@Override public boolean isTracing() {
return true;
}

View File

@@ -27,12 +27,13 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.assertions.SleuthAssertions;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
@@ -53,13 +54,10 @@ public class TraceRestTemplateInterceptorIntegrationTests {
private DefaultTracer tracer;
private StaticApplicationContext publisher = new StaticApplicationContext();
@Before
public void setup() {
this.publisher.refresh();
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher,
new DefaultSpanNamer());
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
new DefaultSpanNamer(), new NoOpSpanLogger(), new NoOpSpanReporter());
this.template.setInterceptors(Arrays.<ClientHttpRequestInterceptor>asList(
new TraceRestTemplateInterceptor(this.tracer)));
TestSpanContextHolder.removeCurrentSpan();

View File

@@ -26,11 +26,12 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.test.web.client.MockMvcClientHttpRequestFactory;
@@ -59,13 +60,10 @@ public class TraceRestTemplateInterceptorTests {
private DefaultTracer tracer;
private StaticApplicationContext publisher = new StaticApplicationContext();
@Before
public void setup() {
this.publisher.refresh();
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher,
new DefaultSpanNamer());
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
new DefaultSpanNamer(), new NoOpSpanLogger(), new NoOpSpanReporter());
this.template.setInterceptors(Arrays.<ClientHttpRequestInterceptor>asList(
new TraceRestTemplateInterceptor(this.tracer)));
TestSpanContextHolder.removeCurrentSpan();

View File

@@ -38,14 +38,11 @@ import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanReporter;
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.TestSpanContextHolder;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
@@ -65,7 +62,7 @@ import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import static junitparams.JUnitParamsRunner.$;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
@RunWith(JUnitParamsRunner.class)
@SpringApplicationConfiguration(classes = { WebClientTests.TestConfiguration.class })
@@ -137,7 +134,17 @@ public class WebClientTests {
then(Span.hexToId(getHeader(response, Span.TRACE_ID_NAME)))
.isEqualTo(currentTraceId);
thenRegisteredClientSentAndReceivedEvents();
thenRegisteredClientSentAndReceivedEvents(spanWithClientEvents());
}
private Span spanWithClientEvents() {
return this.listener.getEvents()
.stream()
.filter(span -> span.logs()
.stream()
.filter(log -> log.getEvent().contains(Span.CLIENT_RECV) || log.getEvent().contains(Span.CLIENT_SEND))
.findFirst().isPresent())
.findFirst().get();
}
private Object[] parametersForShouldAttachTraceIdWhenCallingAnotherService() {
@@ -158,8 +165,8 @@ public class WebClientTests {
provider.get(this);
thenRegisteredClientSentAndReceivedEvents();
then(this.tracer.getCurrentSpan()).isEqualTo(span);
thenRegisteredClientSentAndReceivedEvents(spanWithClientEvents());
}
private Object[] parametersForShouldAttachTraceIdWhenUsingFeignClientWithoutResponseBody() {
@@ -167,10 +174,9 @@ public class WebClientTests {
(ResponseEntityProvider) (tests) -> tests.template.getForEntity("http://fooservice/noresponse", String.class));
}
private void thenRegisteredClientSentAndReceivedEvents() {
then(this.listener.getEvents().size()).isEqualTo(2);
then(this.listener.getEvents().get(0)).isExactlyInstanceOf(ClientSentEvent.class);
then(this.listener.getEvents().get(1)).isExactlyInstanceOf(ClientReceivedEvent.class);
private void thenRegisteredClientSentAndReceivedEvents(Span span) {
then(span).hasLoggedAnEvent(Span.CLIENT_RECV);
then(span).hasLoggedAnEvent(Span.CLIENT_SEND);
}
private Long generatedId() {
@@ -221,27 +227,24 @@ public class WebClientTests {
}
@Component
public static class Listener {
private List<ApplicationEvent> events = new ArrayList<>();
public static class Listener implements SpanReporter {
private List<Span> events = new ArrayList<>();
@EventListener(ClientSentEvent.class)
public void sent(ClientSentEvent event) {
this.events.add(event);
}
@EventListener(ClientReceivedEvent.class)
public void received(ClientReceivedEvent event) {
this.events.add(event);
}
public List<ApplicationEvent> getEvents() {
public List<Span> getEvents() {
return this.events;
}
@Override
public void report(Span span) {
this.events.add(span);
}
}
@RestController
public static class FooController {
@Autowired Tracer tracer;
@RequestMapping(value = "/notrace", method = RequestMethod.GET)
public String notrace(
@RequestHeader(name = Span.TRACE_ID_NAME, required = false) String traceId) {

View File

@@ -2,9 +2,11 @@ package org.springframework.cloud.sleuth.instrument.web.common;
import org.junit.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.instrument.web.TraceFilter;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
@@ -53,6 +55,7 @@ public abstract class AbstractMvcWiremockIntegrationTest extends AbstractMvcInte
@Override
protected void configureMockMvcBuilder(DefaultMockMvcBuilder mockMvcBuilder) {
mockMvcBuilder.addFilters(new TraceFilter(this.tracer, this.traceKeys));
mockMvcBuilder.addFilters(new TraceFilter(this.tracer, this.traceKeys,
new NoOpSpanReporter()));
}
}

View File

@@ -6,8 +6,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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.event.ArrayListSpanAccumulator;
import org.springframework.cloud.sleuth.util.ArrayListSpanAccumulator;
import org.springframework.cloud.sleuth.TraceKeys;
import org.springframework.cloud.sleuth.instrument.web.TraceFilter;
import org.springframework.cloud.sleuth.instrument.web.common.AbstractMvcIntegrationTest;
@@ -32,10 +33,12 @@ public class MultipleHopsIntegrationTests extends AbstractMvcIntegrationTest {
@Autowired Tracer tracer;
@Autowired TraceKeys traceKeys;
@Autowired ArrayListSpanAccumulator arrayListSpanAccumulator;
@Autowired SpanReporter spanReporter;
@Override
protected void configureMockMvcBuilder(DefaultMockMvcBuilder mockMvcBuilder) {
mockMvcBuilder.addFilters(new TraceFilter(this.tracer, this.traceKeys));
mockMvcBuilder.addFilters(new TraceFilter(this.tracer, this.traceKeys,
this.spanReporter));
}
@Test

View File

@@ -18,20 +18,20 @@ package org.springframework.cloud.sleuth.instrument.zuul;
import java.util.Random;
import com.netflix.zuul.context.RequestContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.verify;
import com.netflix.zuul.context.RequestContext;
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
/**
* @author Dave Syer
@@ -39,11 +39,8 @@ import static org.mockito.Mockito.verify;
*/
public class TracePostZuulFilterTests {
private ApplicationEventPublisher publisher = Mockito.mock(ApplicationEventPublisher.class);
private DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(),
new Random(), Mockito.mock(ApplicationEventPublisher.class),
new DefaultSpanNamer());
new Random(), new DefaultSpanNamer(), new NoOpSpanLogger(), new NoOpSpanReporter());
private TracePostZuulFilter filter = new TracePostZuulFilter(this.tracer);
@@ -56,9 +53,9 @@ public class TracePostZuulFilterTests {
@Test
public void filterPublishesEvent() throws Exception {
this.filter.setApplicationEventPublisher(this.publisher);
this.tracer.createSpan("http:start");
Span span = this.tracer.createSpan("http:start");
this.filter.run();
verify(this.publisher).publishEvent(isA(ClientReceivedEvent.class));
then(span).hasLoggedAnEvent(Span.CLIENT_RECV);
}
}

View File

@@ -18,18 +18,19 @@ package org.springframework.cloud.sleuth.instrument.zuul;
import java.util.Random;
import com.netflix.zuul.context.RequestContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.NoOpSpanReporter;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.sampler.NeverSampler;
import org.springframework.cloud.sleuth.trace.DefaultTracer;
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
import org.springframework.context.ApplicationEventPublisher;
import com.netflix.zuul.context.RequestContext;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
@@ -42,11 +43,8 @@ import static org.junit.Assert.assertThat;
*/
public class TracePreZuulFilterTests {
private ApplicationEventPublisher publisher = Mockito
.mock(ApplicationEventPublisher.class);
private DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.publisher, new DefaultSpanNamer());
new DefaultSpanNamer(), new NoOpSpanLogger(), new NoOpSpanReporter());
private TracePreZuulFilter filter = new TracePreZuulFilter(this.tracer);

View File

@@ -26,7 +26,6 @@ import org.springframework.cloud.netflix.zuul.filters.route.RestClientRibbonComm
import org.springframework.cloud.netflix.zuul.filters.route.RibbonCommandContext;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanAccessor;
import org.springframework.context.ApplicationEventPublisher;
import com.netflix.client.http.HttpRequest;
import com.netflix.niws.client.http.RestClient;
@@ -42,7 +41,6 @@ import static org.mockito.Matchers.anyString;
@RunWith(MockitoJUnitRunner.class)
public class TraceRestClientRibbonCommandFactoryTest {
@Mock ApplicationEventPublisher publisher;
@Mock SpanAccessor accessor;
@Mock SpringClientFactory springClientFactory;
TraceRestClientRibbonCommandFactory traceRestClientRibbonCommandFactory;
@@ -52,7 +50,6 @@ public class TraceRestClientRibbonCommandFactoryTest {
public void setup() {
this.traceRestClientRibbonCommandFactory = new TraceRestClientRibbonCommandFactory(
this.springClientFactory, this.accessor);
this.traceRestClientRibbonCommandFactory.setApplicationEventPublisher(this.publisher);
given(this.springClientFactory.getClient(anyString(), any(Class.class))).willReturn(new RestClient());
Span span = Span.builder()
.name("name")

View File

@@ -20,9 +20,6 @@ import org.junit.Test;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.event.SpanAcquiredEvent;
import org.springframework.cloud.sleuth.event.SpanContinuedEvent;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import static org.mockito.BDDMockito.then;
import static org.mockito.Matchers.anyList;
@@ -33,79 +30,79 @@ import static org.mockito.Mockito.times;
/**
* @author Marcin Grzejszczak
*/
public class Slf4jSpanListenerTest {
public class Slf4JSpanLoggerTest {
Span spanWithNameToBeExcluded = Span.builder().name("Hystrix").build();
Span spanWithNameNotToBeExcluded = Span.builder().name("Aspect").build();
String nameExcludingPattern = "^.*Hystrix.*$";
Logger log = Mockito.mock(Logger.class);
Slf4jSpanListener slf4jSpanListener = new Slf4jSpanListener(this.nameExcludingPattern, this.log);
Slf4jSpanLogger slf4JSpanLogger = new Slf4jSpanLogger(this.nameExcludingPattern, this.log);
@Test
public void should_log_when_start_event_arrived_and_pattern_doesnt_match_span_name() throws Exception {
this.slf4jSpanListener.start(new SpanAcquiredEvent(this, this.spanWithNameNotToBeExcluded,
this.spanWithNameNotToBeExcluded));
this.slf4JSpanLogger.logStartedSpan(this.spanWithNameNotToBeExcluded,
this.spanWithNameNotToBeExcluded);
then(this.log).should(times(2)).trace(anyString(), anyList());
}
@Test
public void should_log_once_when_start_event_arrived_and_pattern_matches_only_parent_span_name() throws Exception {
this.slf4jSpanListener.start(new SpanAcquiredEvent(this, this.spanWithNameToBeExcluded,
this.spanWithNameNotToBeExcluded));
this.slf4JSpanLogger.logStartedSpan(this.spanWithNameToBeExcluded,
this.spanWithNameNotToBeExcluded);
then(this.log).should().trace(anyString(), anyList());
}
@Test
public void should_log_when_continue_event_arrived_and_pattern_doesnt_match_span_name() throws Exception {
this.slf4jSpanListener.continued(new SpanContinuedEvent(this,
this.spanWithNameNotToBeExcluded));
this.slf4JSpanLogger.logContinuedSpan(
this.spanWithNameNotToBeExcluded);
then(this.log).should().trace(anyString(), anyList());
}
@Test
public void should_not_log_when_continue_event_arrived_and_pattern_matches_name() throws Exception {
this.slf4jSpanListener.continued(new SpanContinuedEvent(this, this.spanWithNameToBeExcluded));
this.slf4JSpanLogger.logContinuedSpan(this.spanWithNameToBeExcluded);
then(this.log).should(never()).trace(anyString(), anyList());
}
@Test
public void should_log_when_close_event_arrived_and_pattern_doesnt_match_span_name() throws Exception {
this.slf4jSpanListener.stop(new SpanReleasedEvent(this, this.spanWithNameNotToBeExcluded));
this.slf4JSpanLogger.logStoppedSpan(null, this.spanWithNameNotToBeExcluded);
then(this.log).should().trace(anyString(), anyList());
}
@Test
public void should_log_both_spans_when_their_names_dont_match_pattern() throws Exception {
this.slf4jSpanListener.stop(new SpanReleasedEvent(this, this.spanWithNameNotToBeExcluded,
this.spanWithNameNotToBeExcluded));
this.slf4JSpanLogger.logStoppedSpan(this.spanWithNameNotToBeExcluded,
this.spanWithNameNotToBeExcluded);
then(this.log).should(times(2)).trace(anyString(), anyList());
}
@Test
public void should_not_log_any_spans_if_both_match_pattern() throws Exception {
this.slf4jSpanListener.stop(new SpanReleasedEvent(this, this.spanWithNameToBeExcluded,
this.spanWithNameToBeExcluded));
this.slf4JSpanLogger.logStoppedSpan(this.spanWithNameToBeExcluded,
this.spanWithNameToBeExcluded);
then(this.log).should(never()).trace(anyString(), anyList());
}
@Test
public void should_log_only_current_span_if_parent_span_name_matches_pattern() throws Exception {
this.slf4jSpanListener.stop(new SpanReleasedEvent(this, this.spanWithNameNotToBeExcluded,
this.spanWithNameToBeExcluded));
this.slf4JSpanLogger.logStoppedSpan(this.spanWithNameNotToBeExcluded,
this.spanWithNameToBeExcluded);
then(this.log).should().trace(anyString(), anyList());
}
@Test
public void should_log_only_current_span_if_there_is_no_parent() throws Exception {
this.slf4jSpanListener.stop(new SpanReleasedEvent(this, this.spanWithNameNotToBeExcluded));
this.slf4JSpanLogger.logStoppedSpan(null, this.spanWithNameNotToBeExcluded);
then(this.log).should().trace(anyString(), anyList());
}

View File

@@ -24,23 +24,20 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.SpanNamer;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.event.SpanAcquiredEvent;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import org.springframework.cloud.sleuth.log.SpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.sampler.NeverSampler;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
@@ -56,13 +53,13 @@ public class DefaultTracerTests {
public static final String IMPORTANT_WORK_1 = "http:important work 1";
public static final String IMPORTANT_WORK_2 = "http:important work 2";
public static final int NUM_SPANS = 3;
private ApplicationEventPublisher publisher;
private SpanNamer spanNamer = new DefaultSpanNamer();
private SpanLogger spanLogger = Mockito.mock(SpanLogger.class);
private SpanReporter spanReporter = Mockito.mock(SpanReporter.class);
@Before
public void setup() {
TestSpanContextHolder.removeCurrentSpan();
this.publisher = mock(ApplicationEventPublisher.class);
}
@After
@@ -74,7 +71,7 @@ public class DefaultTracerTests {
public void tracingWorks() {
DefaultTracer tracer = new DefaultTracer(NeverSampler.INSTANCE, new Random(),
this.publisher, new DefaultSpanNamer());
new DefaultSpanNamer(), this.spanLogger, this.spanReporter);
Span span = tracer.createSpan(CREATE_SIMPLE_TRACE, new AlwaysSampler());
try {
@@ -84,21 +81,16 @@ public class DefaultTracerTests {
tracer.close(span);
}
verify(this.publisher, times(NUM_SPANS))
.publishEvent(isA(SpanAcquiredEvent.class));
verify(this.publisher, times(NUM_SPANS))
.publishEvent(isA(SpanReleasedEvent.class));
verify(this.spanLogger, times(NUM_SPANS))
.logStartedSpan(Mockito.any(Span.class), Mockito.any(Span.class));
verify(this.spanReporter, times(NUM_SPANS))
.report(Mockito.any(Span.class));
ArgumentCaptor<ApplicationEvent> captor = ArgumentCaptor
.forClass(ApplicationEvent.class);
verify(this.publisher, atLeast(NUM_SPANS)).publishEvent(captor.capture());
ArgumentCaptor<Span> captor = ArgumentCaptor
.forClass(Span.class);
verify(this.spanReporter, atLeast(NUM_SPANS)).report(captor.capture());
List<Span> spans = new ArrayList<>();
for (ApplicationEvent event : captor.getAllValues()) {
if (event instanceof SpanReleasedEvent) {
spans.add(((SpanReleasedEvent) event).getSpan());
}
}
List<Span> spans = new ArrayList<>(captor.getAllValues());
assertThat("spans was wrong size", spans.size(), is(NUM_SPANS));
@@ -113,7 +105,7 @@ public class DefaultTracerTests {
@Test
public void nonExportable() {
DefaultTracer tracer = new DefaultTracer(NeverSampler.INSTANCE, new Random(),
this.publisher, this.spanNamer);
this.spanNamer, this.spanLogger, this.spanReporter);
Span span = tracer.createSpan(CREATE_SIMPLE_TRACE);
assertThat(span.isExportable(), is(false));
}
@@ -121,7 +113,7 @@ public class DefaultTracerTests {
@Test
public void exportable() {
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.publisher, this.spanNamer);
this.spanNamer, this.spanLogger, this.spanReporter);
Span span = tracer.createSpan(CREATE_SIMPLE_TRACE);
assertThat(span.isExportable(), is(true));
}
@@ -129,7 +121,7 @@ public class DefaultTracerTests {
@Test
public void exportableInheritedFromParent() {
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.publisher, this.spanNamer);
this.spanNamer, this.spanLogger, this.spanReporter);
Span span = tracer.createSpan(CREATE_SIMPLE_TRACE, NeverSampler.INSTANCE);
assertThat(span.isExportable(), is(false));
Span child = tracer.createSpan(CREATE_SIMPLE_TRACE_SPAN_NAME + "/child", span);
@@ -139,7 +131,7 @@ public class DefaultTracerTests {
@Test
public void parentNotRemovedIfActiveOnJoin() {
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.publisher, this.spanNamer);
this.spanNamer, this.spanLogger, this.spanReporter);
Span parent = tracer.createSpan(CREATE_SIMPLE_TRACE);
Span span = tracer.createSpan(IMPORTANT_WORK_1, parent);
tracer.close(span);
@@ -149,7 +141,7 @@ public class DefaultTracerTests {
@Test
public void parentRemovedIfNotActiveOnJoin() {
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.publisher, this.spanNamer);
this.spanNamer, this.spanLogger, this.spanReporter);
Span parent = Span.builder().name(CREATE_SIMPLE_TRACE).traceId(1L).spanId(1L)
.build();
Span span = tracer.createSpan(IMPORTANT_WORK_1, parent);
@@ -160,7 +152,7 @@ public class DefaultTracerTests {
@Test
public void grandParentRestoredAfterAutoClose() {
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.publisher, this.spanNamer);
this.spanNamer, this.spanLogger, this.spanReporter);
Span grandParent = tracer.createSpan(CREATE_SIMPLE_TRACE);
Span parent = Span.builder().name(IMPORTANT_WORK_1).traceId(1L).spanId(1L)
.build();
@@ -172,7 +164,7 @@ public class DefaultTracerTests {
@Test
public void shouldUpdateLogsInSpanWhenItGetsContinued() {
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
this.publisher, this.spanNamer);
this.spanNamer, this.spanLogger, this.spanReporter);
Span span = Span.builder().name(IMPORTANT_WORK_1).traceId(1L).spanId(1L)
.build();
Span continuedSpan = tracer.continueSpan(span);

View File

@@ -27,7 +27,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.WebIntegrationTest;
import org.springframework.cloud.sleuth.metric.SpanReporterService;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter;
import org.springframework.cloud.sleuth.zipkin.ZipkinProperties;
import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter;
@@ -81,13 +81,13 @@ public class ZipkinTests extends AbstractIntegrationTest {
@Bean
public ZipkinSpanReporter spanCollector(final ZipkinProperties zipkin,
final SpanReporterService spanReporterService) {
final SpanMetricReporter spanMetricReporter) {
await().until(new Runnable() {
@Override
public void run() {
try {
WaitUntilZipkinIsUpConfig.this.getSpanCollector(zipkin,
spanReporterService);
spanMetricReporter);
}
catch (Exception e) {
log.error("Exception occurred while trying to connect to zipkin ["
@@ -96,13 +96,13 @@ public class ZipkinTests extends AbstractIntegrationTest {
}
}
});
return getSpanCollector(zipkin, spanReporterService);
return getSpanCollector(zipkin, spanMetricReporter);
}
private ZipkinSpanReporter getSpanCollector(ZipkinProperties zipkin,
SpanReporterService spanReporterService) {
SpanMetricReporter spanMetricReporter) {
return new HttpZipkinSpanReporter(zipkin.getBaseUrl(), zipkin.getFlushInterval(),
zipkin.getCompression().isEnabled(), spanReporterService);
zipkin.getCompression().isEnabled(), spanMetricReporter);
}
}

View File

@@ -27,7 +27,7 @@ import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.metric.SpanReporterService;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import org.springframework.cloud.sleuth.sampler.PercentageBasedSampler;
import org.springframework.cloud.sleuth.sampler.SamplerProperties;
import org.springframework.cloud.stream.annotation.EnableBinding;
@@ -64,14 +64,14 @@ public class SleuthStreamAutoConfiguration {
@Bean
@GlobalChannelInterceptor(patterns = SleuthSource.OUTPUT, order = Ordered.HIGHEST_PRECEDENCE)
public ChannelInterceptor zipkinChannelInterceptor(SpanReporterService spanReporterService) {
return new TracerIgnoringChannelInterceptor(spanReporterService);
public ChannelInterceptor zipkinChannelInterceptor(SpanMetricReporter spanMetricReporter) {
return new TracerIgnoringChannelInterceptor(spanMetricReporter);
}
@Bean
public StreamSpanListener sleuthTracer(HostLocator endpointLocator,
SpanReporterService spanReporterService) {
return new StreamSpanListener(endpointLocator, spanReporterService);
SpanMetricReporter spanMetricReporter) {
return new StreamSpanListener(endpointLocator, spanMetricReporter);
}
@Configuration

View File

@@ -23,15 +23,8 @@ import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.cloud.sleuth.event.ServerReceivedEvent;
import org.springframework.cloud.sleuth.event.ServerSentEvent;
import org.springframework.cloud.sleuth.event.SpanAcquiredEvent;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import org.springframework.cloud.sleuth.metric.SpanReporterService;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.integration.annotation.MessageEndpoint;
@@ -44,70 +37,21 @@ import org.springframework.integration.annotation.MessageEndpoint;
* @since 1.0.0
*/
@MessageEndpoint
public class StreamSpanListener {
public static final String CLIENT_RECV = "cr";
public static final String CLIENT_SEND = "cs";
public static final String SERVER_RECV = "sr";
public static final String SERVER_SEND = "ss";
public class StreamSpanListener implements SpanReporter {
private Collection<Span> queue = new ConcurrentLinkedQueue<>();
private final HostLocator endpointLocator;
private final SpanReporterService spanReporterService;
private final SpanMetricReporter spanMetricReporter;
public StreamSpanListener(HostLocator endpointLocator, SpanReporterService spanReporterService) {
public StreamSpanListener(HostLocator endpointLocator, SpanMetricReporter spanMetricReporter) {
this.endpointLocator = endpointLocator;
this.spanReporterService = spanReporterService;
this.spanMetricReporter = spanMetricReporter;
}
public void setQueue(Collection<Span> queue) {
this.queue = queue;
}
@EventListener
@Order(0)
public void start(SpanAcquiredEvent event) {
event.getSpan().logEvent("acquire");
}
@EventListener
@Order(0)
public void serverReceived(ServerReceivedEvent event) {
if (event.getParent() != null && event.getParent().isRemote()) {
event.getParent().logEvent(SERVER_RECV);
}
}
@EventListener
@Order(0)
public void clientSend(ClientSentEvent event) {
event.getSpan().logEvent(CLIENT_SEND);
}
@EventListener
@Order(0)
public void clientReceive(ClientReceivedEvent event) {
event.getSpan().logEvent(CLIENT_RECV);
}
@EventListener
@Order(0)
public void serverSend(ServerSentEvent event) {
if (event.getParent() != null && event.getParent().isRemote()) {
event.getParent().logEvent(SERVER_SEND);
this.queue.add(event.getParent());
}
}
@EventListener
@Order(0)
public void release(SpanReleasedEvent event) {
event.getSpan().logEvent("release");
if (event.getSpan().isExportable()) {
this.queue.add(event.getSpan());
}
}
@InboundChannelAdapter(value = SleuthSource.OUTPUT)
public Spans poll() {
List<Span> result = new ArrayList<>(this.queue);
@@ -121,8 +65,14 @@ public class StreamSpanListener {
if (result.isEmpty()) {
return null;
}
this.spanReporterService.incrementAcceptedSpans(result.size());
this.spanMetricReporter.incrementAcceptedSpans(result.size());
return new Spans(this.endpointLocator.locate(result.get(0)), result);
}
@Override
public void report(Span span) {
if (span.isExportable()) {
this.queue.add(span);
}
}
}

View File

@@ -17,7 +17,7 @@
package org.springframework.cloud.sleuth.stream;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.metric.SpanReporterService;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
@@ -31,10 +31,10 @@ import org.springframework.messaging.support.ChannelInterceptorAdapter;
*/
class TracerIgnoringChannelInterceptor extends ChannelInterceptorAdapter {
private final SpanReporterService spanReporterService;
private final SpanMetricReporter spanMetricReporter;
public TracerIgnoringChannelInterceptor(SpanReporterService spanReporterService) {
this.spanReporterService = spanReporterService;
public TracerIgnoringChannelInterceptor(SpanMetricReporter spanMetricReporter) {
this.spanMetricReporter = spanMetricReporter;
}
/**
@@ -55,9 +55,9 @@ class TracerIgnoringChannelInterceptor extends ChannelInterceptorAdapter {
Spans spans = (Spans) message.getPayload();
int spanNumber = spans.getSpans().size();
if (sent) {
this.spanReporterService.incrementAcceptedSpans(spanNumber);
this.spanMetricReporter.incrementAcceptedSpans(spanNumber);
} else {
this.spanReporterService.incrementDroppedSpans(spanNumber);
this.spanMetricReporter.incrementDroppedSpans(spanNumber);
}
}
}

View File

@@ -35,12 +35,11 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati
import org.springframework.boot.test.SpringApplicationConfiguration;
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.autoconfig.TraceAutoConfiguration;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.cloud.sleuth.event.ServerReceivedEvent;
import org.springframework.cloud.sleuth.event.ServerSentEvent;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.log.SpanLogger;
import org.springframework.cloud.sleuth.metric.TraceMetricsAutoConfiguration;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.stream.StreamSpanListenerTests.TestConfiguration;
@@ -68,6 +67,7 @@ public class StreamSpanListenerTests {
@Autowired ZipkinTestConfiguration test;
@Autowired StreamSpanListener listener;
@Autowired CounterService counterService;
@Autowired SpanReporter spanReporter;
@PostConstruct
public void init() {
@@ -86,20 +86,30 @@ public class StreamSpanListenerTests {
Span parent = Span.builder().traceId(1L).name("http:parent").remote(true)
.build();
Span context = this.tracer.createSpan("http:child", parent);
this.application.publishEvent(new ClientSentEvent(this, context));
this.application
.publishEvent(new ServerReceivedEvent(this, parent, context));
this.application
.publishEvent(new ServerSentEvent(this, parent, context));
this.application.publishEvent(new ClientReceivedEvent(this, context));
context.logEvent(Span.CLIENT_SEND);
logServerReceived(parent);
logServerSent(this.spanReporter, parent);
this.tracer.close(context);
assertEquals(2, this.test.spans.size());
}
void logServerReceived(Span parent) {
if (parent != null && parent.isRemote()) {
parent.logEvent(Span.SERVER_RECV);
}
}
void logServerSent(SpanReporter spanReporter, Span parent) {
if (parent != null && parent.isRemote()) {
parent.logEvent(Span.SERVER_SEND);
spanReporter.report(parent);
}
}
@Test
public void nullSpanName() {
Span span = this.tracer.createSpan(null);
this.application.publishEvent(new ClientSentEvent(this, span));
span.logEvent(Span.CLIENT_SEND);
this.tracer.close(span);
assertEquals(1, this.test.spans.size());
this.listener.poll();
@@ -135,6 +145,11 @@ public class StreamSpanListenerTests {
public void handle(Message<?> msg) {
}
@Bean
SpanLogger spanLogger() {
return new NoOpSpanLogger();
}
@Bean
public Sampler defaultSampler() {
return new AlwaysSampler();

View File

@@ -25,7 +25,7 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.metric.SpanReporterService;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
@@ -40,7 +40,7 @@ import static org.mockito.Mockito.verifyZeroInteractions;
public class TracerIgnoringChannelInterceptorTest {
@Mock MessageChannel messageChannel;
@Mock SpanReporterService spanReporterService;
@Mock SpanMetricReporter spanMetricReporter;
@InjectMocks TracerIgnoringChannelInterceptor tracerIgnoringChannelInterceptor;
@Test
@@ -59,7 +59,7 @@ public class TracerIgnoringChannelInterceptorTest {
this.tracerIgnoringChannelInterceptor.afterSendCompletion(message, this.messageChannel, true, null);
verifyZeroInteractions(this.spanReporterService);
verifyZeroInteractions(this.spanMetricReporter);
}
@Test
@@ -71,7 +71,7 @@ public class TracerIgnoringChannelInterceptorTest {
this.tracerIgnoringChannelInterceptor.afterSendCompletion(message, this.messageChannel, true, null);
BDDMockito.then(this.spanReporterService).should().incrementAcceptedSpans(2);
BDDMockito.then(this.spanMetricReporter).should().incrementAcceptedSpans(2);
}
@Test
@@ -83,6 +83,6 @@ public class TracerIgnoringChannelInterceptorTest {
this.tracerIgnoringChannelInterceptor.afterSendCompletion(message, this.messageChannel, false, null);
BDDMockito.then(this.spanReporterService).should().incrementDroppedSpans(2);
BDDMockito.then(this.spanMetricReporter).should().incrementDroppedSpans(2);
}
}

View File

@@ -16,7 +16,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.commons.logging.Log;
import org.springframework.cloud.sleuth.metric.SpanReporterService;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import zipkin.Codec;
import zipkin.Span;
@@ -41,20 +41,20 @@ public final class HttpZipkinSpanReporter
private final BlockingQueue<Span> pending = new LinkedBlockingQueue<>(1000);
private final Flusher flusher; // Nullable for testing
private final boolean compressionEnabled;
private final SpanReporterService spanReporterService;
private final SpanMetricReporter spanMetricReporter;
/**
* @param baseUrl URL of the zipkin query server instance. Like: http://localhost:9411/
* @param flushInterval in seconds. 0 implies spans are {@link #flush() flushed} externally.
* @param compressionEnabled compress spans using gzip before posting to the zipkin server.
* @param spanReporterService service to count number of accepted / dropped spans
* @param spanMetricReporter service to count number of accepted / dropped spans
*/
public HttpZipkinSpanReporter(String baseUrl, int flushInterval, boolean compressionEnabled,
SpanReporterService spanReporterService) {
SpanMetricReporter spanMetricReporter) {
this.url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + "api/v1/spans";
this.flusher = flushInterval > 0 ? new Flusher(this, flushInterval) : null;
this.compressionEnabled = compressionEnabled;
this.spanReporterService = spanReporterService;
this.spanMetricReporter = spanMetricReporter;
}
/**
@@ -64,9 +64,9 @@ public final class HttpZipkinSpanReporter
*/
@Override
public void report(Span span) {
this.spanReporterService.incrementAcceptedSpans(1);
this.spanMetricReporter.incrementAcceptedSpans(1);
if (!this.pending.offer(span)) {
this.spanReporterService.incrementDroppedSpans(1);
this.spanMetricReporter.incrementDroppedSpans(1);
}
}
@@ -87,7 +87,7 @@ public final class HttpZipkinSpanReporter
// NOTE: https://github.com/openzipkin/zipkin-java/issues/66 will throw instead of return null.
if (json == null) {
log.debug("failed to encode spans, dropping them: " + drained);
this.spanReporterService.incrementDroppedSpans(drained.size());
this.spanMetricReporter.incrementDroppedSpans(drained.size());
return;
}
@@ -102,7 +102,7 @@ public final class HttpZipkinSpanReporter
"error POSTing spans to " + this.url + ": as json: " + new String(json,
UTF_8), e);
}
this.spanReporterService.incrementDroppedSpans(drained.size());
this.spanMetricReporter.incrementDroppedSpans(drained.size());
}
}
@@ -164,6 +164,6 @@ public final class HttpZipkinSpanReporter
this.flusher.scheduler.shutdown();
// throw any outstanding spans on the floor
int dropped = this.pending.drainTo(new LinkedList<>());
this.spanReporterService.incrementDroppedSpans(dropped);
this.spanMetricReporter.incrementDroppedSpans(dropped);
}
}

View File

@@ -28,7 +28,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.sleuth.Sampler;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.cloud.sleuth.metric.SpanReporterService;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import org.springframework.cloud.sleuth.sampler.PercentageBasedSampler;
import org.springframework.cloud.sleuth.sampler.SamplerProperties;
import org.springframework.context.annotation.Bean;
@@ -52,9 +52,9 @@ public class ZipkinAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ZipkinSpanReporter.class)
public ZipkinSpanReporter reporter(SpanReporterService spanReporterService, ZipkinProperties zipkin) {
public ZipkinSpanReporter reporter(SpanMetricReporter spanMetricReporter, ZipkinProperties zipkin) {
return new HttpZipkinSpanReporter(zipkin.getBaseUrl(), zipkin.getFlushInterval(),
zipkin.getCompression().isEnabled(), spanReporterService);
zipkin.getCompression().isEnabled(), spanMetricReporter);
}
@Bean

View File

@@ -23,14 +23,7 @@ import java.util.Map;
import org.springframework.cloud.sleuth.Log;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.cloud.sleuth.event.ServerReceivedEvent;
import org.springframework.cloud.sleuth.event.ServerSentEvent;
import org.springframework.cloud.sleuth.event.SpanAcquiredEvent;
import org.springframework.cloud.sleuth.event.SpanReleasedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.cloud.sleuth.SpanReporter;
import org.springframework.util.StringUtils;
import zipkin.Annotation;
@@ -45,7 +38,7 @@ import zipkin.Endpoint;
*
* @since 1.0.0
*/
public class ZipkinSpanListener {
public class ZipkinSpanListener implements SpanReporter {
private static final List<String> ZIPKIN_START_EVENTS = Arrays.asList(
Constants.CLIENT_RECV, Constants.SERVER_RECV
);
@@ -68,59 +61,6 @@ public class ZipkinSpanListener {
this.endpointLocator = endpointLocator;
}
@EventListener
@Order(0)
public void start(SpanAcquiredEvent event) {
// Zipkin Span.timestamp corresponds with Sleuth's Span.begin
assert event.getSpan().getBegin() != 0;
}
@EventListener
@Order(0)
public void serverReceived(ServerReceivedEvent event) {
if (event.getParent() != null && event.getParent().isRemote()) {
// If an inbound RPC call, it should log a "sr" annotation.
// If possible, it should log a binary annotation of "ca", indicating the
// caller's address (ex X-Forwarded-For header)
event.getParent().logEvent(Constants.SERVER_RECV);
}
}
@EventListener
@Order(0)
public void clientSend(ClientSentEvent event) {
// For an outbound RPC call, it should log a "cs" annotation.
// If possible, it should log a binary annotation of "sa", indicating the
// destination address.
event.getSpan().logEvent(Constants.CLIENT_SEND);
}
@EventListener
@Order(0)
public void clientReceive(ClientReceivedEvent event) {
event.getSpan().logEvent(Constants.CLIENT_RECV);
}
@EventListener
@Order(0)
public void serverSend(ServerSentEvent event) {
if (event.getParent() != null && event.getParent().isRemote()) {
event.getParent().logEvent(Constants.SERVER_SEND);
this.reporter.report(convert(event.getParent()));
}
}
@EventListener
@Order(0)
public void release(SpanReleasedEvent event) {
// Ending a span in zipkin means adding duration and sending it out
// Zipkin Span.duration corresponds with Sleuth's Span.begin and end
assert event.getSpan().getEnd() != 0;
if (event.getSpan().isExportable()) {
this.reporter.report(convert(event.getSpan()));
}
}
/**
* Converts a given Sleuth span to a Zipkin Span.
* <ul>
@@ -232,4 +172,8 @@ public class ZipkinSpanListener {
}
}
@Override
public void report(Span span) {
this.reporter.report(convert(span));
}
}

View File

@@ -2,8 +2,8 @@ package org.springframework.cloud.sleuth.zipkin;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.cloud.sleuth.metric.CounterServiceBasedSpanReporterService;
import org.springframework.cloud.sleuth.metric.SpanReporterService;
import org.springframework.cloud.sleuth.metric.CounterServiceBasedSpanMetricReporter;
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
import zipkin.Span;
import zipkin.junit.HttpFailure;
@@ -16,14 +16,14 @@ public class HttpZipkinSpanReporterTest {
@Rule public final ZipkinRule zipkin = new ZipkinRule();
InMemorySpanCounter inMemorySpanCounter = new InMemorySpanCounter();
SpanReporterService spanReporterService = new CounterServiceBasedSpanReporterService("accepted", "dropped",
SpanMetricReporter spanMetricReporter = new CounterServiceBasedSpanMetricReporter("accepted", "dropped",
this.inMemorySpanCounter);
HttpZipkinSpanReporter reporter = new HttpZipkinSpanReporter(
this.zipkin.httpUrl(),
0, // so that tests can drive flushing explicitly
false, // disable compression
this.spanReporterService
this.spanMetricReporter
);
@Test
@@ -72,7 +72,7 @@ public class HttpZipkinSpanReporterTest {
this.zipkin.httpUrl(),
0, // so that tests can drive flushing explicitly
false, // enable compression
this.spanReporterService
this.spanMetricReporter
);
this.reporter.report(span(1L, "foo"));

View File

@@ -28,12 +28,11 @@ import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfigurati
import org.springframework.boot.test.SpringApplicationConfiguration;
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.autoconfig.TraceAutoConfiguration;
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
import org.springframework.cloud.sleuth.event.ClientSentEvent;
import org.springframework.cloud.sleuth.event.ServerReceivedEvent;
import org.springframework.cloud.sleuth.event.ServerSentEvent;
import org.springframework.cloud.sleuth.log.NoOpSpanLogger;
import org.springframework.cloud.sleuth.log.SpanLogger;
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
import org.springframework.cloud.sleuth.zipkin.ZipkinSpanListenerTests.TestConfiguration;
import org.springframework.context.ApplicationContext;
@@ -55,17 +54,11 @@ import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
public class ZipkinSpanListenerTests {
@Autowired
private Tracer tracer;
@Autowired
private ApplicationContext application;
@Autowired
private ZipkinTestConfiguration test;
@Autowired
private ZipkinSpanListener listener;
@Autowired Tracer tracer;
@Autowired ApplicationContext application;
@Autowired ZipkinTestConfiguration test;
@Autowired ZipkinSpanListener listener;
@Autowired SpanReporter spanReporter;
@PostConstruct
public void init() {
@@ -130,14 +123,26 @@ public class ZipkinSpanListenerTests {
@Test
public void rpcAnnotations() {
Span context = this.tracer.createSpan("http:child", this.parent);
this.application.publishEvent(new ClientSentEvent(this, context));
this.application.publishEvent(new ServerReceivedEvent(this, this.parent, context));
this.application.publishEvent(new ServerSentEvent(this, this.parent, context));
this.application.publishEvent(new ClientReceivedEvent(this, context));
context.logEvent(Span.CLIENT_SEND);
logServerReceived(this.parent);
logServerSent(this.spanReporter, this.parent);
this.tracer.close(context);
assertEquals(2, this.test.spans.size());
}
void logServerReceived(Span parent) {
if (parent != null && parent.isRemote()) {
parent.logEvent(Span.SERVER_RECV);
}
}
void logServerSent(SpanReporter spanReporter, Span parent) {
if (parent != null && parent.isRemote()) {
parent.logEvent(Span.SERVER_SEND);
spanReporter.report(parent);
}
}
@Test
public void appendsLocalComponentTagIfNoZipkinLogIsPresent() {
this.parent.logEvent("hystrix/retry");
@@ -181,6 +186,11 @@ public class ZipkinSpanListenerTests {
@Import({ ZipkinTestConfiguration.class, ZipkinAutoConfiguration.class, TraceAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class })
protected static class TestConfiguration {
@Bean
SpanLogger spanLogger() {
return new NoOpSpanLogger();
}
}
@Configuration