[#168] Introduced local components for async
Added changes following review
* added comments
* added javadocs
* added naming basing on @SpanName and toString()
* added default 'async' naming if there is no overriden span name
* removed TraceDelegate after review
* introduced SpanNamer
fixes #168
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
||||
/**
|
||||
* Default implementation of SpanNamer that tries to get the Span name as follows:
|
||||
*
|
||||
* <li>
|
||||
* <ul>from the @SpanName annotation if one is present</ul>
|
||||
* <ul>from the toString() of the delegate if it's not the
|
||||
* default {@link Object#toString()}</ul>
|
||||
* <ul>the default provided value</ul>
|
||||
* </li>
|
||||
*
|
||||
* @see org.springframework.cloud.sleuth.SpanName
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class DefaultSpanNamer implements SpanNamer {
|
||||
|
||||
@Override
|
||||
public String name(Object object, String defaultValue) {
|
||||
SpanName annotation = AnnotationUtils
|
||||
.findAnnotation(object.getClass(), SpanName.class);
|
||||
String spanName = annotation != null ? annotation.value() : object.toString();
|
||||
// If there is no overridden toString method we'll put a constant value
|
||||
if (isDefaultToString(object, spanName)) {
|
||||
return defaultValue;
|
||||
}
|
||||
return spanName;
|
||||
}
|
||||
|
||||
private static boolean isDefaultToString(Object delegate, String spanName) {
|
||||
return (delegate.getClass().getName() + "@" +
|
||||
Integer.toHexString(delegate.hashCode())).equals(spanName);
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,7 @@ public class Span {
|
||||
public static final List<String> HEADERS = Arrays.asList(SPAN_ID_NAME, TRACE_ID_NAME,
|
||||
SPAN_NAME_NAME, PARENT_ID_NAME, PROCESS_ID_NAME, NOT_SAMPLED_NAME);
|
||||
public static final String SPAN_EXPORT_NAME = "X-Span-Export";
|
||||
public static final String SPAN_LOCAL_COMPONENT_TAG_NAME = "lc";
|
||||
|
||||
private final long begin;
|
||||
private long end = 0;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* Annotation to provide the name for the Span. You should annotate all your
|
||||
* custom {@link java.lang.Runnable} or {@link java.util.concurrent.Callable} classes
|
||||
* for the instrumentation logic to pick up how to name the span.
|
||||
*
|
||||
* If you're using anonymous instances for those classes then you should override the
|
||||
* {@code toString()} method. That way that value will be picked as a span name at
|
||||
* runtime.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface SpanName {
|
||||
/**
|
||||
* Name of the span to be resolved at runtime
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Describes how for a given object a span should be named. In the vast majority
|
||||
* of cases a name should be provided explicitly. In case of instrumentation
|
||||
* where the name has to be resolved at runtime this interface will provide
|
||||
* the name of the span.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public interface SpanNamer {
|
||||
|
||||
/**
|
||||
* Retrieves the span name for the given object.
|
||||
*
|
||||
* @param object - object for which span name should be picked
|
||||
* @param defaultValue - the default valued to be returned if span name can't be calculated
|
||||
* @return span name
|
||||
*/
|
||||
String name(Object object, String defaultValue);
|
||||
}
|
||||
@@ -25,8 +25,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
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.Sampler;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
import org.springframework.cloud.sleuth.metric.CounterServiceBasedSpanReporterService;
|
||||
import org.springframework.cloud.sleuth.metric.NoOpSpanReporterService;
|
||||
import org.springframework.cloud.sleuth.metric.SleuthMetricProperties;
|
||||
@@ -60,8 +63,9 @@ public class TraceAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(Tracer.class)
|
||||
public DefaultTracer traceManager(Sampler sampler, Random random,
|
||||
ApplicationEventPublisher publisher) {
|
||||
return new DefaultTracer(sampler, random, publisher);
|
||||
ApplicationEventPublisher publisher,
|
||||
SpanNamer spanNamer) {
|
||||
return new DefaultTracer(sampler, random, publisher, spanNamer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -70,6 +74,18 @@ public class TraceAutoConfiguration {
|
||||
return new SleuthMetricProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TraceKeys traceKeys() {
|
||||
return new TraceKeys();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SpanNamer spanNamer() {
|
||||
return new DefaultSpanNamer();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(CounterService.class)
|
||||
@ConditionalOnMissingBean(SpanReporterService.class)
|
||||
|
||||
@@ -53,6 +53,10 @@ public class TraceKeys {
|
||||
|
||||
private Message message = new Message();
|
||||
|
||||
private Hystrix hystrix = new Hystrix();
|
||||
|
||||
private Async async = new Async();
|
||||
|
||||
public Http getHttp() {
|
||||
return this.http;
|
||||
}
|
||||
@@ -61,6 +65,14 @@ public class TraceKeys {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
public Hystrix getHystrix() {
|
||||
return this.hystrix;
|
||||
}
|
||||
|
||||
public Async getAsync() {
|
||||
return this.async;
|
||||
}
|
||||
|
||||
public void setHttp(Http http) {
|
||||
this.http = http;
|
||||
}
|
||||
@@ -69,6 +81,14 @@ public class TraceKeys {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public void setHystrix(Hystrix hystrix) {
|
||||
this.hystrix = hystrix;
|
||||
}
|
||||
|
||||
public void setAsync(Async async) {
|
||||
this.async = async;
|
||||
}
|
||||
|
||||
public static class Message {
|
||||
|
||||
private Payload payload = new Payload();
|
||||
@@ -283,4 +303,97 @@ public class TraceKeys {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trace keys related to Hystrix processing
|
||||
*/
|
||||
public static class Hystrix {
|
||||
|
||||
/**
|
||||
* Prefix for header names if they are added as tags.
|
||||
*/
|
||||
private String prefix = "";
|
||||
|
||||
/**
|
||||
* Name of the command key
|
||||
*/
|
||||
private String commandKey = "commandKey";
|
||||
|
||||
public String getPrefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
public String getCommandKey() {
|
||||
return this.commandKey;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public void setCommandKey(String commandKey) {
|
||||
this.commandKey = commandKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Trace keys related to async processing
|
||||
*/
|
||||
public static class Async {
|
||||
|
||||
/**
|
||||
* Prefix for header names if they are added as tags.
|
||||
*/
|
||||
private String prefix = "";
|
||||
|
||||
/**
|
||||
* Name of the thread that executed the async method
|
||||
*/
|
||||
private String threadNameKey = "thread";
|
||||
|
||||
/**
|
||||
* Simple name of the class with a method annotated with {@code @Async}
|
||||
* from which the asynchronous process started
|
||||
*/
|
||||
private String classNameKey = "class";
|
||||
|
||||
/**
|
||||
* Name of the method annotated with {@code @Async}
|
||||
*/
|
||||
private String methodNameKey = "method";
|
||||
|
||||
public String getPrefix() {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
public String getThreadNameKey() {
|
||||
return this.threadNameKey;
|
||||
}
|
||||
|
||||
public String getClassNameKey() {
|
||||
return this.classNameKey;
|
||||
}
|
||||
|
||||
public String getMethodNameKey() {
|
||||
return this.methodNameKey;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public void setThreadNameKey(String threadNameKey) {
|
||||
this.threadNameKey = threadNameKey;
|
||||
}
|
||||
|
||||
public void setClassNameKey(String classNameKey) {
|
||||
this.classNameKey = classNameKey;
|
||||
}
|
||||
|
||||
public void setMethodNameKey(String methodNameKey) {
|
||||
this.methodNameKey = methodNameKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
@@ -49,8 +50,8 @@ public class AsyncDefaultAutoConfiguration extends AsyncConfigurerSupport {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TraceAsyncAspect traceAsyncAspect(Tracer tracer) {
|
||||
return new TraceAsyncAspect(tracer);
|
||||
public TraceAsyncAspect traceAsyncAspect(Tracer tracer, TraceKeys traceKeys) {
|
||||
return new TraceAsyncAspect(tracer, traceKeys);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,11 +16,17 @@
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.async;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.cloud.sleuth.DefaultSpanNamer;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
@@ -28,9 +34,13 @@ import org.springframework.cloud.sleuth.Tracer;
|
||||
*/
|
||||
public class LazyTraceExecutor implements Executor {
|
||||
|
||||
private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass());
|
||||
|
||||
private Tracer tracer;
|
||||
private final BeanFactory beanFactory;
|
||||
private final Executor delegate;
|
||||
private TraceKeys traceKeys;
|
||||
private SpanNamer spanNamer;
|
||||
|
||||
public LazyTraceExecutor(BeanFactory beanFactory, Executor delegate) {
|
||||
this.beanFactory = beanFactory;
|
||||
@@ -45,9 +55,38 @@ public class LazyTraceExecutor implements Executor {
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
this.delegate.execute(command);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.delegate.execute(new TraceRunnable(this.tracer, command));
|
||||
this.delegate.execute(new LocalComponentTraceRunnable(this.tracer, traceKeys(), spanNamer(), command));
|
||||
}
|
||||
|
||||
// due to some race conditions trace keys might not be ready yet
|
||||
private TraceKeys traceKeys() {
|
||||
if (this.traceKeys == null) {
|
||||
try {
|
||||
this.traceKeys = this.beanFactory.getBean(TraceKeys.class);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
log.warn("TraceKeys bean not found - will provide a manually created instance");
|
||||
return new TraceKeys();
|
||||
}
|
||||
}
|
||||
return this.traceKeys;
|
||||
}
|
||||
|
||||
// due to some race conditions trace keys might not be ready yet
|
||||
private SpanNamer spanNamer() {
|
||||
if (this.spanNamer == null) {
|
||||
try {
|
||||
this.spanNamer = this.beanFactory.getBean(SpanNamer.class);
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
log.warn("SpanNamer bean not found - will provide a manually created instance");
|
||||
return new DefaultSpanNamer();
|
||||
}
|
||||
}
|
||||
return this.spanNamer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.instrument.async;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
|
||||
/**
|
||||
*
|
||||
* Callable that starts a span that is a local component span.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class LocalComponentTraceCallable<V> extends TraceCallable<V> {
|
||||
|
||||
protected static final String ASYNC_COMPONENT = "async";
|
||||
|
||||
private final TraceKeys traceKeys;
|
||||
|
||||
public LocalComponentTraceCallable(Tracer tracer, TraceKeys traceKeys,
|
||||
SpanNamer spanNamer, Callable<V> delegate) {
|
||||
super(tracer, spanNamer, delegate);
|
||||
this.traceKeys = traceKeys;
|
||||
}
|
||||
|
||||
public LocalComponentTraceCallable(Tracer tracer, TraceKeys traceKeys,
|
||||
SpanNamer spanNamer, String name, Callable<V> delegate) {
|
||||
super(tracer, spanNamer, delegate, name);
|
||||
this.traceKeys = traceKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V call() throws Exception {
|
||||
Span span = startSpan();
|
||||
try {
|
||||
return this.getDelegate().call();
|
||||
}
|
||||
finally {
|
||||
close(span);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Span startSpan() {
|
||||
Span span = getTracer().joinTrace(getSpanName(), getParent());
|
||||
getTracer().addTag(Span.SPAN_LOCAL_COMPONENT_TAG_NAME, ASYNC_COMPONENT);
|
||||
getTracer().addTag(this.traceKeys.getAsync().getPrefix() +
|
||||
this.traceKeys.getAsync().getThreadNameKey(), Thread.currentThread().getName());
|
||||
return span;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.instrument.async;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
|
||||
/**
|
||||
*
|
||||
* Runnable that starts a span that is a local component span.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class LocalComponentTraceRunnable extends TraceRunnable {
|
||||
|
||||
protected static final String ASYNC_COMPONENT = "async";
|
||||
|
||||
private final TraceKeys traceKeys;
|
||||
|
||||
public LocalComponentTraceRunnable(Tracer tracer, TraceKeys traceKeys,
|
||||
SpanNamer spanNamer, Runnable delegate) {
|
||||
super(tracer, spanNamer, delegate);
|
||||
this.traceKeys = traceKeys;
|
||||
}
|
||||
|
||||
public LocalComponentTraceRunnable(Tracer tracer, TraceKeys traceKeys,
|
||||
SpanNamer spanNamer, Runnable delegate, String name) {
|
||||
super(tracer, spanNamer, delegate, name);
|
||||
this.traceKeys = traceKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Span span = startSpan();
|
||||
try {
|
||||
this.getDelegate().run();
|
||||
}
|
||||
finally {
|
||||
close(span);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Span startSpan() {
|
||||
Span span = getTracer().joinTrace(getSpanName(), getParent());
|
||||
getTracer().addTag(Span.SPAN_LOCAL_COMPONENT_TAG_NAME, ASYNC_COMPONENT);
|
||||
getTracer().addTag(this.traceKeys.getAsync().getPrefix() +
|
||||
this.traceKeys.getAsync().getThreadNameKey(), Thread.currentThread().getName());
|
||||
return span;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
|
||||
/**
|
||||
* Aspect that creates a new Span for running threads executing methods annotated with
|
||||
@@ -36,15 +37,21 @@ public class TraceAsyncAspect {
|
||||
private static final String ASYNC_COMPONENT = "async";
|
||||
|
||||
private final Tracer tracer;
|
||||
private final TraceKeys traceKeys;
|
||||
|
||||
public TraceAsyncAspect(Tracer tracer) {
|
||||
public TraceAsyncAspect(Tracer tracer, TraceKeys traceKeys) {
|
||||
this.tracer = tracer;
|
||||
this.traceKeys = traceKeys;
|
||||
}
|
||||
|
||||
@Around("execution (@org.springframework.scheduling.annotation.Async * *.*(..))")
|
||||
public Object traceBackgroundThread(final ProceedingJoinPoint pjp) throws Throwable {
|
||||
String spanName = ASYNC_COMPONENT + ":" + pjp.getTarget().getClass().getSimpleName();
|
||||
Span span = this.tracer.startTrace(spanName);
|
||||
Span span = this.tracer.startTrace(pjp.getSignature().getName());
|
||||
this.tracer.addTag(Span.SPAN_LOCAL_COMPONENT_TAG_NAME, ASYNC_COMPONENT);
|
||||
this.tracer.addTag(this.traceKeys.getAsync().getPrefix() +
|
||||
this.traceKeys.getAsync().getClassNameKey(), pjp.getTarget().getClass().getSimpleName());
|
||||
this.tracer.addTag(this.traceKeys.getAsync().getPrefix() +
|
||||
this.traceKeys.getAsync().getMethodNameKey(), pjp.getSignature().getName());
|
||||
try {
|
||||
return pjp.proceed();
|
||||
} finally {
|
||||
|
||||
@@ -19,19 +19,35 @@ package org.springframework.cloud.sleuth.instrument.async;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
/**
|
||||
* Callable that passes Span between threads. The Span name is
|
||||
* taken either from the passed value or from the {@link SpanNamer}
|
||||
* interface.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class TraceCallable<V> extends TraceDelegate<Callable<V>> implements Callable<V> {
|
||||
public class TraceCallable<V> implements Callable<V> {
|
||||
|
||||
public TraceCallable(Tracer tracer, Callable<V> delegate) {
|
||||
super(tracer, delegate);
|
||||
private final Tracer tracer;
|
||||
private final SpanNamer spanNamer;
|
||||
private final Callable<V> delegate;
|
||||
private final String name;
|
||||
private final Span parent;
|
||||
|
||||
public TraceCallable(Tracer tracer, SpanNamer spanNamer, Callable<V> delegate) {
|
||||
this(tracer, spanNamer, delegate, null);
|
||||
}
|
||||
|
||||
public TraceCallable(Tracer tracer, Callable<V> delegate, String name) {
|
||||
super(tracer, delegate, name);
|
||||
public TraceCallable(Tracer tracer, SpanNamer spanNamer, Callable<V> delegate, String name) {
|
||||
this.tracer = tracer;
|
||||
this.spanNamer = spanNamer;
|
||||
this.delegate = delegate;
|
||||
this.name = name;
|
||||
this.parent = tracer.getCurrentSpan();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,4 +61,35 @@ public class TraceCallable<V> extends TraceDelegate<Callable<V>> implements Call
|
||||
}
|
||||
}
|
||||
|
||||
protected Span startSpan() {
|
||||
return this.tracer.joinTrace(getSpanName(), this.parent);
|
||||
}
|
||||
|
||||
protected String getSpanName() {
|
||||
if (this.name != null) {
|
||||
return this.name;
|
||||
}
|
||||
return this.spanNamer.name(this.delegate, "async");
|
||||
}
|
||||
|
||||
protected void close(Span span) {
|
||||
this.tracer.close(span);
|
||||
}
|
||||
|
||||
public Tracer getTracer() {
|
||||
return this.tracer;
|
||||
}
|
||||
|
||||
public Callable<V> getDelegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Span getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.instrument.async;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
/**
|
||||
* Trace Callable that continues a span instead of creating a new one
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class TraceContinuingCallable<V> extends TraceCallable<V> implements Callable<V> {
|
||||
|
||||
public TraceContinuingCallable(Tracer tracer, SpanNamer spanNamer, Callable<V> delegate) {
|
||||
super(tracer, spanNamer, delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Span startSpan() {
|
||||
return getTracer().continueSpan(getParent());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void close(Span span) {
|
||||
getTracer().detach(span);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2015 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.instrument.async;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public abstract class TraceDelegate<T> {
|
||||
|
||||
private static final String ASYNC_COMPONENT = "async";
|
||||
|
||||
private final Tracer tracer;
|
||||
private final T delegate;
|
||||
private final String name;
|
||||
private final Span parent;
|
||||
|
||||
public TraceDelegate(Tracer tracer, T delegate) {
|
||||
this(tracer, delegate, null);
|
||||
}
|
||||
|
||||
public TraceDelegate(Tracer tracer, T delegate, String name) {
|
||||
this.tracer = tracer;
|
||||
this.delegate = delegate;
|
||||
this.name = name;
|
||||
this.parent = tracer.getCurrentSpan();
|
||||
}
|
||||
|
||||
protected void close(Span span) {
|
||||
this.tracer.close(span);
|
||||
}
|
||||
|
||||
protected Span startSpan() {
|
||||
return this.tracer.joinTrace(getSpanName(), this.parent);
|
||||
}
|
||||
|
||||
protected String getSpanName() {
|
||||
return this.name == null ?
|
||||
ASYNC_COMPONENT + ":" + Thread.currentThread().getName()
|
||||
: this.name;
|
||||
}
|
||||
|
||||
public Tracer getTracer() {
|
||||
return this.tracer;
|
||||
}
|
||||
|
||||
public T getDelegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Span getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TraceDelegate{" +
|
||||
"tracer=" + this.tracer +
|
||||
", delegate=" + this.delegate +
|
||||
", name=" + this.name +
|
||||
", parent=" + this.parent +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -17,23 +17,39 @@
|
||||
package org.springframework.cloud.sleuth.instrument.async;
|
||||
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
/**
|
||||
* Runnable that passes Span between threads. The Span name is
|
||||
* taken either from the passed value or from the {@link SpanNamer}
|
||||
* interface.
|
||||
*
|
||||
* @author Spencer Gibb
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class TraceRunnable extends TraceDelegate<Runnable> implements Runnable {
|
||||
public class TraceRunnable implements Runnable {
|
||||
|
||||
public TraceRunnable(Tracer tracer, Runnable delegate) {
|
||||
super(tracer, delegate);
|
||||
private final Tracer tracer;
|
||||
private final SpanNamer spanNamer;
|
||||
private final Runnable delegate;
|
||||
private final String name;
|
||||
private final Span parent;
|
||||
|
||||
public TraceRunnable(Tracer tracer, SpanNamer spanNamer, Runnable delegate) {
|
||||
this(tracer, spanNamer, delegate, null);
|
||||
}
|
||||
|
||||
public TraceRunnable(Tracer tracer, Runnable delegate, String name) {
|
||||
super(tracer, delegate, name);
|
||||
public TraceRunnable(Tracer tracer, SpanNamer spanNamer, Runnable delegate, String name) {
|
||||
this.tracer = tracer;
|
||||
this.spanNamer = spanNamer;
|
||||
this.delegate = delegate;
|
||||
this.name = name;
|
||||
this.parent = tracer.getCurrentSpan();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
public void run() {
|
||||
Span span = startSpan();
|
||||
try {
|
||||
this.getDelegate().run();
|
||||
@@ -42,4 +58,35 @@ public class TraceRunnable extends TraceDelegate<Runnable> implements Runnable {
|
||||
close(span);
|
||||
}
|
||||
}
|
||||
|
||||
protected Span startSpan() {
|
||||
return this.tracer.joinTrace(getSpanName(), this.parent);
|
||||
}
|
||||
|
||||
protected String getSpanName() {
|
||||
if (this.name != null) {
|
||||
return this.name;
|
||||
}
|
||||
return this.spanNamer.name(this.delegate, "async");
|
||||
}
|
||||
|
||||
protected void close(Span span) {
|
||||
this.tracer.close(span);
|
||||
}
|
||||
|
||||
public Tracer getTracer() {
|
||||
return this.tracer;
|
||||
}
|
||||
|
||||
public Runnable getDelegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Span getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,10 @@ import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
|
||||
/**
|
||||
* A decorator class for {@link ExecutorService} to support tracing in Executors
|
||||
* @author Gaurav Rai Mazra
|
||||
@@ -34,20 +37,27 @@ public class TraceableExecutorService implements ExecutorService {
|
||||
final ExecutorService delegate;
|
||||
final Tracer tracer;
|
||||
private final String spanName;
|
||||
final TraceKeys traceKeys;
|
||||
final SpanNamer spanNamer;
|
||||
|
||||
public TraceableExecutorService(final ExecutorService delegate, final Tracer tracer) {
|
||||
this(delegate, tracer, null);
|
||||
public TraceableExecutorService(final ExecutorService delegate, final Tracer tracer,
|
||||
TraceKeys traceKeys, SpanNamer spanNamer) {
|
||||
this(delegate, tracer, traceKeys, spanNamer, null);
|
||||
}
|
||||
|
||||
public TraceableExecutorService(final ExecutorService delegate, final Tracer tracer, String spanName) {
|
||||
public TraceableExecutorService(final ExecutorService delegate, final Tracer tracer,
|
||||
TraceKeys traceKeys, SpanNamer spanNamer, String spanName) {
|
||||
this.delegate = delegate;
|
||||
this.tracer = tracer;
|
||||
this.spanName = spanName;
|
||||
this.traceKeys = traceKeys;
|
||||
this.spanNamer = spanNamer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable command) {
|
||||
final Runnable r = new TraceRunnable(this.tracer, command, this.spanName);
|
||||
final Runnable r = new LocalComponentTraceRunnable(this.tracer, this.traceKeys,
|
||||
this.spanNamer, command, this.spanName);
|
||||
this.delegate.execute(r);
|
||||
}
|
||||
|
||||
@@ -78,19 +88,22 @@ public class TraceableExecutorService implements ExecutorService {
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
Callable<T> c = new TraceCallable<>(this.tracer, task, this.spanName);
|
||||
Callable<T> c = new LocalComponentTraceCallable<>(this.tracer, this.traceKeys,
|
||||
this.spanNamer, this.spanName, task);
|
||||
return this.delegate.submit(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Runnable task, T result) {
|
||||
Runnable r = new TraceRunnable(this.tracer, task, this.spanName);
|
||||
Runnable r = new LocalComponentTraceRunnable(this.tracer, this.traceKeys,
|
||||
this.spanNamer, task, this.spanName);
|
||||
return this.delegate.submit(r, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<?> submit(Runnable task) {
|
||||
Runnable r = new TraceRunnable(this.tracer, task, this.spanName);
|
||||
Runnable r = new LocalComponentTraceRunnable(this.tracer, this.traceKeys,
|
||||
this.spanNamer, task, this.spanName);
|
||||
return this.delegate.submit(r);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
|
||||
/**
|
||||
* A decorator class for {@link ScheduledExecutorService} to support tracing in Executors
|
||||
@@ -30,8 +32,9 @@ import org.springframework.cloud.sleuth.Tracer;
|
||||
*/
|
||||
public class TraceableScheduledExecutorService extends TraceableExecutorService implements ScheduledExecutorService {
|
||||
|
||||
public TraceableScheduledExecutorService(final ScheduledExecutorService delegate, final Tracer tracer) {
|
||||
super(delegate, tracer);
|
||||
public TraceableScheduledExecutorService(final ScheduledExecutorService delegate,
|
||||
final Tracer tracer, TraceKeys traceKeys, SpanNamer spanNamer) {
|
||||
super(delegate, tracer, traceKeys, spanNamer);
|
||||
}
|
||||
|
||||
private ScheduledExecutorService getScheduledExecutorService() {
|
||||
@@ -40,27 +43,25 @@ public class TraceableScheduledExecutorService extends TraceableExecutorService
|
||||
|
||||
@Override
|
||||
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
|
||||
Runnable r = new TraceRunnable(this.tracer, command);
|
||||
Runnable r = new LocalComponentTraceRunnable(this.tracer, this.traceKeys, this.spanNamer, command);
|
||||
return getScheduledExecutorService().schedule(r, delay, unit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
|
||||
Callable<V> c = new TraceCallable<>(this.tracer,callable);
|
||||
Callable<V> c = new LocalComponentTraceCallable<>(this.tracer, this.traceKeys, this.spanNamer, callable);
|
||||
return getScheduledExecutorService().schedule(c, delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
|
||||
Runnable r = new TraceRunnable(this.tracer, command);
|
||||
Runnable r = new LocalComponentTraceRunnable(this.tracer, this.traceKeys, this.spanNamer, command);
|
||||
return getScheduledExecutorService().scheduleAtFixedRate(r, initialDelay, period, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
|
||||
Runnable r = new TraceRunnable(this.tracer, command);
|
||||
Runnable r = new LocalComponentTraceRunnable(this.tracer, this.traceKeys, this.spanNamer, command);
|
||||
return getScheduledExecutorService().scheduleWithFixedDelay(r, initialDelay, delay, unit);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.springframework.cloud.sleuth.instrument.hystrix;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -14,7 +15,7 @@ import com.netflix.hystrix.HystrixCommand;
|
||||
public class SleuthHystrixAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
SleuthHystrixConcurrencyStrategy sleuthHystrixConcurrencyStrategy(Tracer tracer) {
|
||||
return new SleuthHystrixConcurrencyStrategy(tracer);
|
||||
SleuthHystrixConcurrencyStrategy sleuthHystrixConcurrencyStrategy(Tracer tracer, TraceKeys traceKeys) {
|
||||
return new SleuthHystrixConcurrencyStrategy(tracer, traceKeys);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package org.springframework.cloud.sleuth.instrument.hystrix;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import com.netflix.hystrix.strategy.HystrixPlugins;
|
||||
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
|
||||
public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
|
||||
|
||||
@@ -18,9 +17,11 @@ public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy
|
||||
.getLogger(SleuthHystrixConcurrencyStrategy.class);
|
||||
|
||||
private final Tracer tracer;
|
||||
private final TraceKeys traceKeys;
|
||||
|
||||
public SleuthHystrixConcurrencyStrategy(Tracer tracer) {
|
||||
public SleuthHystrixConcurrencyStrategy(Tracer tracer, TraceKeys traceKeys) {
|
||||
this.tracer = tracer;
|
||||
this.traceKeys = traceKeys;
|
||||
try {
|
||||
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
|
||||
}
|
||||
@@ -41,17 +42,19 @@ public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy
|
||||
|
||||
@Override
|
||||
public <T> Callable<T> wrapCallable(Callable<T> callable) {
|
||||
return new HystrixTraceCallable<T>(this.tracer, callable);
|
||||
return new HystrixTraceCallable<T>(this.tracer, this.traceKeys, callable);
|
||||
}
|
||||
|
||||
private static class HystrixTraceCallable<S> implements Callable<S> {
|
||||
|
||||
private Tracer tracer;
|
||||
private TraceKeys traceKeys;
|
||||
private Callable<S> callable;
|
||||
private Span parent;
|
||||
|
||||
public HystrixTraceCallable(Tracer tracer, Callable<S> callable) {
|
||||
public HystrixTraceCallable(Tracer tracer, TraceKeys traceKeys, Callable<S> callable) {
|
||||
this.tracer = tracer;
|
||||
this.traceKeys = traceKeys;
|
||||
this.callable = callable;
|
||||
this.parent = tracer.getCurrentSpan();
|
||||
}
|
||||
@@ -64,8 +67,10 @@ public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy
|
||||
span = this.tracer.continueSpan(span);
|
||||
}
|
||||
else {
|
||||
span = this.tracer.startTrace(HYSTRIX_COMPONENT +
|
||||
":" + Thread.currentThread().getName());
|
||||
span = this.tracer.startTrace(HYSTRIX_COMPONENT);
|
||||
this.tracer.addTag(Span.SPAN_LOCAL_COMPONENT_TAG_NAME, HYSTRIX_COMPONENT);
|
||||
this.tracer.addTag(this.traceKeys.getAsync().getPrefix() +
|
||||
this.traceKeys.getAsync().getThreadNameKey(), Thread.currentThread().getName());
|
||||
created = true;
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
import com.netflix.hystrix.HystrixCommand;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
|
||||
/**
|
||||
* Abstraction over {@code HystrixCommand} that wraps command execution with Trace setting
|
||||
@@ -36,18 +37,23 @@ public abstract class TraceCommand<R> extends HystrixCommand<R> {
|
||||
private static final String HYSTRIX_COMPONENT = "hystrix";
|
||||
|
||||
private final Tracer tracer;
|
||||
private final TraceKeys traceKeys;
|
||||
private final Span parentSpan;
|
||||
|
||||
protected TraceCommand(Tracer tracer, Setter setter) {
|
||||
protected TraceCommand(Tracer tracer, TraceKeys traceKeys, Setter setter) {
|
||||
super(setter);
|
||||
this.tracer = tracer;
|
||||
this.traceKeys = traceKeys;
|
||||
this.parentSpan = tracer.getCurrentSpan();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected R run() throws Exception {
|
||||
String spanName = HYSTRIX_COMPONENT + ":" + getCommandKey().name();
|
||||
Span span = this.tracer.joinTrace(spanName, this.parentSpan);
|
||||
String commandKeyName = getCommandKey().name();
|
||||
Span span = this.tracer.joinTrace(commandKeyName, this.parentSpan);
|
||||
this.tracer.addTag(Span.SPAN_LOCAL_COMPONENT_TAG_NAME, HYSTRIX_COMPONENT);
|
||||
this.tracer.addTag(this.traceKeys.getHystrix().getPrefix() +
|
||||
this.traceKeys.getHystrix().getCommandKey(), commandKeyName);
|
||||
try {
|
||||
return doRun();
|
||||
}
|
||||
|
||||
@@ -25,8 +25,9 @@ import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.async.TraceCallable;
|
||||
import org.springframework.cloud.sleuth.instrument.async.TraceContinuingCallable;
|
||||
import org.springframework.web.context.request.async.WebAsyncTask;
|
||||
|
||||
/**
|
||||
@@ -43,14 +44,19 @@ import org.springframework.web.context.request.async.WebAsyncTask;
|
||||
* </ul>
|
||||
* <p/>
|
||||
* For controllers an around aspect is created that wraps the {@link Callable#call()}
|
||||
* method execution in {@link TraceCallable}
|
||||
* method execution in {@link org.springframework.cloud.sleuth.instrument.async.TraceCallable}
|
||||
* <p/>
|
||||
*
|
||||
* This aspect will continue a span created by the TraceFilter. It will not create
|
||||
* a new span - since the one in TraceFilter will wait until processing has been
|
||||
* finished
|
||||
*
|
||||
* @see org.springframework.web.bind.annotation.RestController
|
||||
* @see org.springframework.stereotype.Controller
|
||||
* @see org.springframework.web.client.RestOperations
|
||||
* @see TraceCallable
|
||||
* @see org.springframework.cloud.sleuth.instrument.async.TraceCallable
|
||||
* @see Tracer
|
||||
* @see TraceFilter
|
||||
*
|
||||
* @author Tomasz Nurkewicz, 4financeIT
|
||||
* @author Marcin Grzejszczak, 4financeIT
|
||||
@@ -60,16 +66,17 @@ import org.springframework.web.context.request.async.WebAsyncTask;
|
||||
@Aspect
|
||||
public class TraceWebAspect {
|
||||
|
||||
private static final String ASYNC_COMPONENT = "async";
|
||||
private static final Log log = org.apache.commons.logging.LogFactory
|
||||
.getLog(TraceWebAspect.class);
|
||||
|
||||
private final Tracer tracer;
|
||||
private final SpanAccessor accessor;
|
||||
private final SpanNamer spanNamer;
|
||||
|
||||
public TraceWebAspect(Tracer tracer, SpanAccessor accessor) {
|
||||
public TraceWebAspect(Tracer tracer, SpanAccessor accessor, SpanNamer spanNamer) {
|
||||
this.tracer = tracer;
|
||||
this.accessor = accessor;
|
||||
this.spanNamer = spanNamer;
|
||||
}
|
||||
|
||||
@Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
|
||||
@@ -103,19 +110,13 @@ public class TraceWebAspect {
|
||||
if (this.accessor.isTracing()) {
|
||||
log.debug("Wrapping callable with span ["
|
||||
+ this.accessor.getCurrentSpan() + "]");
|
||||
return new TraceCallable<>(this.tracer, callable);
|
||||
return new TraceContinuingCallable<>(this.tracer, this.spanNamer, callable);
|
||||
}
|
||||
else {
|
||||
return callable;
|
||||
}
|
||||
}
|
||||
|
||||
private String spanName(ProceedingJoinPoint pjp) {
|
||||
return ASYNC_COMPONENT + ":" +
|
||||
pjp.getTarget().getClass().getSimpleName() + "#" +
|
||||
"method=" + pjp.getSignature().getName();
|
||||
}
|
||||
|
||||
@Around("anyControllerOrRestControllerWithPublicWebAsyncTaskMethod()")
|
||||
public Object wrapWebAsyncTaskWithCorrelationId(ProceedingJoinPoint pjp) throws Throwable {
|
||||
final WebAsyncTask<?> webAsyncTask = (WebAsyncTask<?>) pjp.proceed();
|
||||
@@ -125,8 +126,8 @@ public class TraceWebAspect {
|
||||
+ this.accessor.getCurrentSpan() + "]");
|
||||
Field callableField = WebAsyncTask.class.getDeclaredField("callable");
|
||||
callableField.setAccessible(true);
|
||||
callableField.set(webAsyncTask, new TraceCallable<>(this.tracer,
|
||||
webAsyncTask.getCallable(), spanName(pjp)));
|
||||
callableField.set(webAsyncTask, new TraceContinuingCallable<>(this.tracer,
|
||||
this.spanNamer, webAsyncTask.getCallable()));
|
||||
} catch (NoSuchFieldException ex) {
|
||||
log.warn("Cannot wrap webAsyncTask's callable with TraceCallable", ex);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
@@ -67,8 +68,8 @@ public class TraceWebAutoConfiguration {
|
||||
private TraceKeys traceKeys;
|
||||
|
||||
@Bean
|
||||
public TraceWebAspect traceWebAspect() {
|
||||
return new TraceWebAspect(this.tracer, this.accessor);
|
||||
public TraceWebAspect traceWebAspect(SpanNamer spanNamer) {
|
||||
return new TraceWebAspect(this.tracer, this.accessor, spanNamer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -53,7 +53,7 @@ abstract class AbstractTraceHttpRequestInterceptor
|
||||
if (!span.isExportable()) {
|
||||
setHeader(request, Span.NOT_SAMPLED_NAME, "true");
|
||||
}
|
||||
setHeader(request, Span.SPAN_NAME_NAME, span.getName().toString());
|
||||
setHeader(request, Span.SPAN_NAME_NAME, span.getName());
|
||||
setIdHeader(request, Span.PARENT_ID_NAME, getParentId(span));
|
||||
setHeader(request, Span.PROCESS_ID_NAME, span.getProcessId());
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
*/
|
||||
package org.springframework.cloud.sleuth.instrument.web.client;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import com.netflix.hystrix.HystrixCommand;
|
||||
import com.netflix.hystrix.HystrixCommandGroupKey;
|
||||
import com.netflix.hystrix.HystrixCommandKey;
|
||||
@@ -22,12 +26,9 @@ import feign.InvocationHandlerFactory;
|
||||
import feign.InvocationHandlerFactory.MethodHandler;
|
||||
import feign.Target;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
import org.springframework.cloud.sleuth.instrument.hystrix.TraceCommand;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import static feign.Util.checkNotNull;
|
||||
|
||||
/**
|
||||
@@ -38,12 +39,14 @@ final class SleuthHystrixInvocationHandler implements InvocationHandler {
|
||||
private final Target<?> target;
|
||||
private final Map<Method, MethodHandler> dispatch;
|
||||
private final Tracer tracer;
|
||||
private final TraceKeys traceKeys;
|
||||
|
||||
SleuthHystrixInvocationHandler(Target<?> target, Map<Method, MethodHandler> dispatch,
|
||||
Tracer tracer) {
|
||||
Tracer tracer, TraceKeys traceKeys) {
|
||||
this.tracer = checkNotNull(tracer, "traceManager");
|
||||
this.target = checkNotNull(target, "target");
|
||||
this.dispatch = checkNotNull(dispatch, "dispatch");
|
||||
this.traceKeys = checkNotNull(traceKeys, "traceKeys");
|
||||
}
|
||||
|
||||
@Override public Object invoke(final Object proxy, final Method method,
|
||||
@@ -54,7 +57,7 @@ final class SleuthHystrixInvocationHandler implements InvocationHandler {
|
||||
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
|
||||
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey));
|
||||
|
||||
HystrixCommand<Object> hystrixCommand = new TraceCommand<Object>(this.tracer,
|
||||
HystrixCommand<Object> hystrixCommand = new TraceCommand<Object>(this.tracer, this.traceKeys,
|
||||
setter) {
|
||||
@Override public Object doRun() throws Exception {
|
||||
try {
|
||||
@@ -79,15 +82,18 @@ final class SleuthHystrixInvocationHandler implements InvocationHandler {
|
||||
static final class Factory implements InvocationHandlerFactory {
|
||||
|
||||
private final Tracer tracer;
|
||||
private final TraceKeys traceKeys;
|
||||
|
||||
public Factory(Tracer tracer) {
|
||||
public Factory(Tracer tracer, TraceKeys traceKeys) {
|
||||
this.tracer = tracer;
|
||||
this.traceKeys = traceKeys;
|
||||
}
|
||||
|
||||
@Override public InvocationHandler create(
|
||||
@SuppressWarnings("rawtypes") Target target,
|
||||
Map<Method, MethodHandler> dispatch) {
|
||||
return new SleuthHystrixInvocationHandler(target, dispatch, this.tracer);
|
||||
return new SleuthHystrixInvocationHandler(target, dispatch, this.tracer,
|
||||
this.traceKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.event.ClientReceivedEvent;
|
||||
import org.springframework.cloud.sleuth.event.ClientSentEvent;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
import org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixAutoConfiguration;
|
||||
import org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixConcurrencyStrategy;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
@@ -88,9 +89,9 @@ public class TraceFeignClientAutoConfiguration {
|
||||
@ConditionalOnClass(HystrixCommand.class)
|
||||
@ConditionalOnMissingBean(SleuthHystrixConcurrencyStrategy.class)
|
||||
@ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing = true)
|
||||
public Feign.Builder feignHystrixBuilder(Tracer tracer) {
|
||||
public Feign.Builder feignHystrixBuilder(Tracer tracer, TraceKeys traceKeys) {
|
||||
return HystrixFeign.builder().invocationHandlerFactory(
|
||||
new SleuthHystrixInvocationHandler.Factory(tracer));
|
||||
new SleuthHystrixInvocationHandler.Factory(tracer, traceKeys));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -21,6 +21,7 @@ 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;
|
||||
@@ -41,11 +42,14 @@ public class DefaultTracer implements Tracer {
|
||||
|
||||
private final Random random;
|
||||
|
||||
private final SpanNamer spanNamer;
|
||||
|
||||
public DefaultTracer(Sampler defaultSampler, Random random,
|
||||
ApplicationEventPublisher publisher) {
|
||||
ApplicationEventPublisher publisher, SpanNamer spanNamer) {
|
||||
this.defaultSampler = defaultSampler;
|
||||
this.random = random;
|
||||
this.publisher = publisher;
|
||||
this.spanNamer = spanNamer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,7 +202,7 @@ public class DefaultTracer implements Tracer {
|
||||
@Override
|
||||
public <V> Callable<V> wrap(Callable<V> callable) {
|
||||
if (isTracing()) {
|
||||
return new TraceCallable<>(this, callable);
|
||||
return new TraceCallable<>(this, this.spanNamer, callable);
|
||||
}
|
||||
return callable;
|
||||
}
|
||||
@@ -211,7 +215,7 @@ public class DefaultTracer implements Tracer {
|
||||
@Override
|
||||
public Runnable wrap(Runnable runnable) {
|
||||
if (isTracing()) {
|
||||
return new TraceRunnable(this, runnable);
|
||||
return new TraceRunnable(this, this.spanNamer, runnable);
|
||||
}
|
||||
return runnable;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
public class DefaultSpanNamerTest {
|
||||
|
||||
DefaultSpanNamer defaultSpanNamer = new DefaultSpanNamer();
|
||||
|
||||
@Test
|
||||
public void should_return_value_of_span_name_from_annotation() throws Exception {
|
||||
then(this.defaultSpanNamer.name(new ClassWithAnnotation(), "default")).isEqualTo("somevalue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_value_of_span_name_from_to_string_if_annotation_is_missing() throws Exception {
|
||||
then(this.defaultSpanNamer.name(fromAnonymousClassWithCustomToString(), "default")).isEqualTo("some-other-value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_return_default_value_if_tostring_wasnt_overridden() throws Exception {
|
||||
then(this.defaultSpanNamer.name(new ClassWithoutToString(), "default")).isEqualTo("default");
|
||||
}
|
||||
|
||||
@SpanName("somevalue")
|
||||
static class ClassWithAnnotation {}
|
||||
|
||||
private Runnable fromAnonymousClassWithCustomToString() {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "some-other-value";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static class ClassWithoutToString {}
|
||||
}
|
||||
@@ -54,6 +54,16 @@ public class SpanAssert extends AbstractAssert<SpanAssert, Span> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanAssert nameStartsWith(String string) {
|
||||
isNotNull();
|
||||
if (!this.actual.getName().startsWith(string)) {
|
||||
String message = String.format("Expected span's name to start with <%s> but it was equal to <%s>", string, this.actual.getName());
|
||||
log.error(message);
|
||||
failWithMessage(message);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanAssert hasNameNotEqualTo(String name) {
|
||||
isNotNull();
|
||||
if (Objects.equals(this.actual.getName(), name)) {
|
||||
@@ -63,4 +73,33 @@ public class SpanAssert extends AbstractAssert<SpanAssert, Span> {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanAssert isALocalComponentSpan() {
|
||||
isNotNull();
|
||||
if (!this.actual.tags().containsKey(Span.SPAN_LOCAL_COMPONENT_TAG_NAME)) {
|
||||
String message = String.format("Expected span to be a local component. "
|
||||
+ "LC tag is missing. Found tags are <%s>", this.actual.tags());
|
||||
log.error(message);
|
||||
failWithMessage(message);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SpanAssert hasATag(String tagKey, String tagValue) {
|
||||
isNotNull();
|
||||
if (!this.actual.tags().containsKey(tagKey)) {
|
||||
String message = String.format("Expected span to have the tag with key <%s>. "
|
||||
+ "Found tags are <%s>", tagKey, this.actual.tags());
|
||||
log.error(message);
|
||||
failWithMessage(message);
|
||||
}
|
||||
String foundTagValue = this.actual.tags().get(tagKey);
|
||||
if (!foundTagValue.equals(tagValue)) {
|
||||
String message = String.format("Expected span to have the tag with key <%s> and value <%s>. "
|
||||
+ "Found value for that tag is <%s>", tagKey, tagValue, foundTagValue);
|
||||
log.error(message);
|
||||
failWithMessage(message);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -10,22 +10,23 @@ 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.Span;
|
||||
import org.springframework.cloud.sleuth.SpanName;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.async.TraceCallable;
|
||||
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.assertj.core.api.BDDAssertions.then;
|
||||
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TraceCallableTests {
|
||||
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
Tracer tracer = new DefaultTracer(new AlwaysSampler(),
|
||||
new Random(), Mockito.mock(ApplicationEventPublisher.class));
|
||||
new Random(), Mockito.mock(ApplicationEventPublisher.class), new DefaultSpanNamer());
|
||||
|
||||
@After
|
||||
public void clean() {
|
||||
@@ -71,6 +72,23 @@ public class TraceCallableTests {
|
||||
then(secondSpan).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_take_name_of_span_from_span_name_annotation()
|
||||
throws Exception {
|
||||
Span span = whenATraceKeepingCallableGetsSubmitted();
|
||||
|
||||
then(span).hasNameEqualTo("some-callable-name-from-annotation");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_take_name_of_span_from_to_string_if_span_name_annotation_is_missing()
|
||||
throws Exception {
|
||||
Span span = whenCallableGetsSubmitted(
|
||||
thatRetrievesTraceFromThreadLocal());
|
||||
|
||||
then(span).hasNameEqualTo("some-callable-name-from-to-string");
|
||||
}
|
||||
|
||||
private Span givenSpanIsAlreadyActive() {
|
||||
return this.tracer.startTrace("http:parent");
|
||||
}
|
||||
@@ -81,6 +99,11 @@ public class TraceCallableTests {
|
||||
public Span call() throws Exception {
|
||||
return TestSpanContextHolder.getCurrentSpan();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "some-callable-name-from-to-string";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -91,13 +114,29 @@ public class TraceCallableTests {
|
||||
|
||||
private Span whenCallableGetsSubmitted(Callable<Span> callable)
|
||||
throws InterruptedException, java.util.concurrent.ExecutionException {
|
||||
return this.executor.submit(new TraceCallable<>(this.tracer, callable))
|
||||
return this.executor.submit(new TraceCallable<>(this.tracer, new DefaultSpanNamer(), callable))
|
||||
.get();
|
||||
}
|
||||
private Span whenATraceKeepingCallableGetsSubmitted()
|
||||
throws InterruptedException, java.util.concurrent.ExecutionException {
|
||||
return this.executor.submit(new TraceCallable<>(this.tracer, new DefaultSpanNamer(),
|
||||
new TraceKeepingCallable())).get();
|
||||
}
|
||||
|
||||
private Span whenNonTraceableCallableGetsSubmitted(Callable<Span> callable)
|
||||
throws InterruptedException, java.util.concurrent.ExecutionException {
|
||||
return this.executor.submit(callable).get();
|
||||
}
|
||||
|
||||
@SpanName("some-callable-name-from-annotation")
|
||||
static class TraceKeepingCallable implements Callable<Span> {
|
||||
public Span span;
|
||||
|
||||
@Override
|
||||
public Span call() throws Exception {
|
||||
this.span = TestSpanContextHolder.getCurrentSpan();
|
||||
return this.span;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +1,24 @@
|
||||
package org.springframework.cloud.sleuth.instrument.async;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
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.Span;
|
||||
import org.springframework.cloud.sleuth.SpanName;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.async.TraceRunnable;
|
||||
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 java.util.Random;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@@ -24,7 +26,7 @@ public class TraceRunnableTests {
|
||||
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
Tracer tracer = new DefaultTracer(new AlwaysSampler(),
|
||||
new Random(), Mockito.mock(ApplicationEventPublisher.class));
|
||||
new Random(), Mockito.mock(ApplicationEventPublisher.class), new DefaultSpanNamer());
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
@@ -70,6 +72,27 @@ public class TraceRunnableTests {
|
||||
then(secondSpan).as("unexpected span").isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_take_name_of_span_from_span_name_annotation()
|
||||
throws Exception {
|
||||
TraceKeepingRunnable traceKeepingRunnable = runnableThatRetrievesTraceFromThreadLocal();
|
||||
|
||||
whenRunnableGetsSubmitted(traceKeepingRunnable);
|
||||
|
||||
then(traceKeepingRunnable.span).hasNameEqualTo("some-runnable-name-from-annotation");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_take_name_of_span_from_to_string_if_span_name_annotation_is_missing()
|
||||
throws Exception {
|
||||
final AtomicReference<Span> span = new AtomicReference<>();
|
||||
Runnable runnable = runnableWithCustomToString(span);
|
||||
|
||||
whenRunnableGetsSubmitted(runnable);
|
||||
|
||||
then(span.get()).hasNameEqualTo("some-runnable-name-from-to-string");
|
||||
}
|
||||
|
||||
private TraceKeepingRunnable runnableThatRetrievesTraceFromThreadLocal() {
|
||||
return new TraceKeepingRunnable();
|
||||
}
|
||||
@@ -78,8 +101,8 @@ public class TraceRunnableTests {
|
||||
whenRunnableGetsSubmitted(runnable);
|
||||
}
|
||||
|
||||
private void whenRunnableGetsSubmitted(Runnable callable) throws Exception {
|
||||
this.executor.submit(new TraceRunnable(this.tracer, callable)).get();
|
||||
private void whenRunnableGetsSubmitted(Runnable runnable) throws Exception {
|
||||
this.executor.submit(new TraceRunnable(this.tracer, new DefaultSpanNamer(), runnable)).get();
|
||||
}
|
||||
|
||||
private void whenNonTraceableRunnableGetsSubmitted(Runnable callable)
|
||||
@@ -87,6 +110,20 @@ public class TraceRunnableTests {
|
||||
this.executor.submit(callable).get();
|
||||
}
|
||||
|
||||
private Runnable runnableWithCustomToString(final AtomicReference<Span> span) {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
span.set(TestSpanContextHolder.getCurrentSpan());
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "some-runnable-name-from-to-string";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@SpanName("some-runnable-name-from-annotation")
|
||||
static class TraceKeepingRunnable implements Runnable {
|
||||
public Span span;
|
||||
|
||||
|
||||
@@ -16,7 +16,9 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanNamer;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
|
||||
import org.springframework.cloud.sleuth.trace.DefaultTracer;
|
||||
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
|
||||
@@ -30,6 +32,7 @@ public class TraceableExecutorServiceTests {
|
||||
private static int TOTAL_THREADS = 10;
|
||||
|
||||
@Mock ApplicationEventPublisher publisher;
|
||||
@Mock SpanNamer spanNamer;
|
||||
Tracer tracer;
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(3);
|
||||
ExecutorService traceManagerableExecutorService;
|
||||
@@ -37,8 +40,10 @@ public class TraceableExecutorServiceTests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher);
|
||||
this.traceManagerableExecutorService = new TraceableExecutorService(this.executorService, this.tracer);
|
||||
this.tracer = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher,
|
||||
spanNamer);
|
||||
this.traceManagerableExecutorService = new TraceableExecutorService(this.executorService,
|
||||
this.tracer, new TraceKeys(), this.spanNamer);
|
||||
TestSpanContextHolder.removeCurrentSpan();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,15 +6,18 @@ import com.jayway.awaitility.Awaitility;
|
||||
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
|
||||
import com.netflix.hystrix.strategy.HystrixPlugins;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
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.netflix.hystrix.EnableHystrix;
|
||||
import org.springframework.cloud.sleuth.Sampler;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.DefaultTestAutoConfiguration;
|
||||
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;
|
||||
@@ -36,6 +39,7 @@ public class HystrixAnnotationsIntegrationTests {
|
||||
Tracer tracer;
|
||||
|
||||
@BeforeClass
|
||||
@AfterClass
|
||||
public static void reset() {
|
||||
HystrixPlugins.reset();
|
||||
}
|
||||
@@ -43,29 +47,33 @@ public class HystrixAnnotationsIntegrationTests {
|
||||
@After
|
||||
public void cleanTrace() {
|
||||
TestSpanContextHolder.removeCurrentSpan();
|
||||
HystrixPlugins.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_set_span_on_an_hystrix_command_annotated_method() {
|
||||
public void should_continue_current_span_when_executed_a_hystrix_command_annotated_method() {
|
||||
Span span = givenASpanInCurrentThread();
|
||||
|
||||
whenHystrixCommandAnnotatedMethodGetsExecuted();
|
||||
|
||||
thenTraceIdIsPassedFromTheCurrentThreadToTheHystrixOne(span);
|
||||
thenSpanInHystrixThreadIsContinued(span);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_create_new_span_with_thread_name_when_executed_a_hystrix_command_annotated_method() {
|
||||
whenHystrixCommandAnnotatedMethodGetsExecuted();
|
||||
|
||||
thenSpanInHystrixThreadIsCreated();
|
||||
}
|
||||
|
||||
private Span givenASpanInCurrentThread() {
|
||||
Span span = this.tracer.startTrace("http:existing");
|
||||
this.tracer.continueSpan(span);
|
||||
return span;
|
||||
return this.tracer.startTrace("http:existing");
|
||||
}
|
||||
|
||||
private void whenHystrixCommandAnnotatedMethodGetsExecuted() {
|
||||
this.catcher.invokeLogicWrappedInHystrixCommand();
|
||||
}
|
||||
|
||||
private void thenTraceIdIsPassedFromTheCurrentThreadToTheHystrixOne(final Span span) {
|
||||
private void thenSpanInHystrixThreadIsContinued(final Span span) {
|
||||
then(span).isNotNull();
|
||||
Awaitility.await().until(new Runnable() {
|
||||
@Override
|
||||
@@ -80,6 +88,17 @@ public class HystrixAnnotationsIntegrationTests {
|
||||
});
|
||||
}
|
||||
|
||||
private void thenSpanInHystrixThreadIsCreated() {
|
||||
Awaitility.await().until(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
then(HystrixAnnotationsIntegrationTests.this.catcher.getSpan())
|
||||
.nameStartsWith("hystrix")
|
||||
.isALocalComponentSpan();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@DefaultTestAutoConfiguration
|
||||
@EnableHystrix
|
||||
@Configuration
|
||||
@@ -90,6 +109,11 @@ public class HystrixAnnotationsIntegrationTests {
|
||||
return new HystrixCommandInvocationSpanCatcher();
|
||||
}
|
||||
|
||||
@Bean
|
||||
Sampler sampler() {
|
||||
return new AlwaysSampler();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class HystrixCommandInvocationSpanCatcher {
|
||||
@@ -119,5 +143,9 @@ public class HystrixAnnotationsIntegrationTests {
|
||||
}
|
||||
return this.spanCaughtFromHystrixThread.get().getName();
|
||||
}
|
||||
|
||||
public Span getSpan() {
|
||||
return this.spanCaughtFromHystrixThread.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.springframework.cloud.sleuth.instrument.hystrix;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import com.netflix.hystrix.HystrixCommandKey;
|
||||
import com.netflix.hystrix.HystrixCommandProperties;
|
||||
import com.netflix.hystrix.HystrixThreadPoolProperties;
|
||||
import com.netflix.hystrix.strategy.HystrixPlugins;
|
||||
@@ -9,8 +10,10 @@ 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.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
|
||||
import org.springframework.cloud.sleuth.trace.DefaultTracer;
|
||||
import org.springframework.cloud.sleuth.trace.TestSpanContextHolder;
|
||||
@@ -18,13 +21,13 @@ import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
import static com.netflix.hystrix.HystrixCommand.Setter.withGroupKey;
|
||||
import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey;
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
|
||||
|
||||
public class TraceCommandTests {
|
||||
|
||||
static final long EXPECTED_TRACE_ID = 1L;
|
||||
Tracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
|
||||
Mockito.mock(ApplicationEventPublisher.class));
|
||||
Mockito.mock(ApplicationEventPublisher.class), new DefaultSpanNamer());
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -49,6 +52,16 @@ public class TraceCommandTests {
|
||||
then(secondSpanFromHystrix.getSavedSpan())
|
||||
.as("saved span as remnant of first span").isNull();
|
||||
}
|
||||
@Test
|
||||
public void should_create_a_local_span_with_proper_tags_when_hystrix_command_gets_executed()
|
||||
throws Exception {
|
||||
Span spanFromHystrix = whenCommandIsExecuted(traceReturningCommand());
|
||||
|
||||
then(spanFromHystrix)
|
||||
.isALocalComponentSpan()
|
||||
.hasNameEqualTo("traceCommandKey")
|
||||
.hasATag("commandKey", "traceCommandKey");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_run_Hystrix_command_with_span_passed_from_parent_thread() {
|
||||
@@ -67,12 +80,13 @@ public class TraceCommandTests {
|
||||
}
|
||||
|
||||
private TraceCommand<Span> traceReturningCommand() {
|
||||
return new TraceCommand<Span>(this.tracer,
|
||||
return new TraceCommand<Span>(this.tracer, new TraceKeys(),
|
||||
withGroupKey(asKey("group"))
|
||||
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties
|
||||
.Setter().withCoreSize(1).withMaxQueueSize(1))
|
||||
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
|
||||
.withExecutionTimeoutEnabled(false))) {
|
||||
.withExecutionTimeoutEnabled(false))
|
||||
.andCommandKey(HystrixCommandKey.Factory.asKey("traceCommandKey"))) {
|
||||
@Override
|
||||
public Span doRun() throws Exception {
|
||||
return TestSpanContextHolder.getCurrentSpan();
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.springframework.cloud.sleuth.instrument.web;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import com.jayway.awaitility.Awaitility;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -20,8 +21,6 @@ import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.jayway.awaitility.Awaitility;
|
||||
|
||||
import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@@ -53,9 +52,12 @@ public class TraceAsyncIntegrationTests {
|
||||
Awaitility.await().until(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
then(span)
|
||||
.hasTraceIdEqualTo(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getTraceId())
|
||||
.hasNameNotEqualTo(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpanName());
|
||||
then(TraceAsyncIntegrationTests.this.classPerformingAsyncLogic.getSpan())
|
||||
.hasTraceIdEqualTo(span.getTraceId())
|
||||
.hasNameEqualTo("invokeAsynchronousLogic")
|
||||
.isALocalComponentSpan()
|
||||
.hasATag("class", "ClassPerformingAsyncLogic")
|
||||
.hasATag("method", "invokeAsynchronousLogic");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -91,18 +93,8 @@ public class TraceAsyncIntegrationTests {
|
||||
this.span.set(TestSpanContextHolder.getCurrentSpan());
|
||||
}
|
||||
|
||||
public Long getTraceId() {
|
||||
if (this.span.get() == null) {
|
||||
return null;
|
||||
}
|
||||
return this.span.get().getTraceId();
|
||||
}
|
||||
|
||||
public String getSpanName() {
|
||||
if (this.span.get() != null && this.span.get().getName() == null) {
|
||||
return null;
|
||||
}
|
||||
return this.span.get().getName();
|
||||
public Span getSpan() {
|
||||
return this.span.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.Random;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.sleuth.DefaultSpanNamer;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.cloud.sleuth.instrument.TraceKeys;
|
||||
@@ -46,7 +47,7 @@ public class TraceFilterMockChainIntegrationTests {
|
||||
private StaticApplicationContext context = new StaticApplicationContext();
|
||||
|
||||
private Tracer tracer = new DefaultTracer(new AlwaysSampler(),
|
||||
new Random(), this.context);
|
||||
new Random(), this.context, new DefaultSpanNamer());
|
||||
private TraceKeys traceKeys = new TraceKeys();
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Random;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
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.Tracer;
|
||||
@@ -68,7 +69,7 @@ public class TraceFilterTests {
|
||||
public void init() {
|
||||
initMocks(this);
|
||||
this.tracer = new DefaultTracer(new DelegateSampler(), new Random(),
|
||||
this.publisher) {
|
||||
this.publisher, new DefaultSpanNamer()) {
|
||||
@Override
|
||||
protected Span createSpan(Span span, Span saved) {
|
||||
TraceFilterTests.this.span = super.createSpan(span, saved);
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.web.client;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -27,6 +24,7 @@ import java.util.Random;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.sleuth.DefaultSpanNamer;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
|
||||
import org.springframework.cloud.sleuth.trace.DefaultTracer;
|
||||
@@ -42,6 +40,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -61,7 +62,8 @@ public class TraceRestTemplateInterceptorTests {
|
||||
@Before
|
||||
public void setup() {
|
||||
this.publisher.refresh();
|
||||
this.traces = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher);
|
||||
this.traces = new DefaultTracer(new AlwaysSampler(), new Random(), this.publisher,
|
||||
new DefaultSpanNamer());
|
||||
this.template.setInterceptors(Arrays.<ClientHttpRequestInterceptor>asList(
|
||||
new TraceRestTemplateInterceptor(this.traces)));
|
||||
TestSpanContextHolder.removeCurrentSpan();
|
||||
|
||||
@@ -23,6 +23,7 @@ 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.sampler.AlwaysSampler;
|
||||
import org.springframework.cloud.sleuth.trace.DefaultTracer;
|
||||
@@ -40,7 +41,9 @@ public class TracePostZuulFilterTests {
|
||||
|
||||
private ApplicationEventPublisher publisher = Mockito.mock(ApplicationEventPublisher.class);
|
||||
|
||||
private DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(), Mockito.mock(ApplicationEventPublisher.class));
|
||||
private DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(),
|
||||
new Random(), Mockito.mock(ApplicationEventPublisher.class),
|
||||
new DefaultSpanNamer());
|
||||
|
||||
private TracePostZuulFilter filter = new TracePostZuulFilter(this.tracer);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ 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.Span;
|
||||
import org.springframework.cloud.sleuth.sampler.AlwaysSampler;
|
||||
import org.springframework.cloud.sleuth.sampler.NeverSampler;
|
||||
@@ -45,7 +46,7 @@ public class TracePreZuulFilterTests {
|
||||
.mock(ApplicationEventPublisher.class);
|
||||
|
||||
private DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
|
||||
this.publisher);
|
||||
this.publisher, new DefaultSpanNamer());
|
||||
|
||||
private TracePreZuulFilter filter = new TracePreZuulFilter(this.tracer);
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.springframework.cloud.sleuth.DefaultSpanNamer;
|
||||
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.SpanReleasedEvent;
|
||||
@@ -54,6 +56,7 @@ public class DefaultTracerTests {
|
||||
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();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -70,7 +73,7 @@ public class DefaultTracerTests {
|
||||
public void tracingWorks() {
|
||||
|
||||
DefaultTracer tracer = new DefaultTracer(NeverSampler.INSTANCE, new Random(),
|
||||
this.publisher);
|
||||
this.publisher, new DefaultSpanNamer());
|
||||
|
||||
Span span = tracer.startTrace(CREATE_SIMPLE_TRACE, new AlwaysSampler());
|
||||
try {
|
||||
@@ -109,7 +112,7 @@ public class DefaultTracerTests {
|
||||
@Test
|
||||
public void nonExportable() {
|
||||
DefaultTracer tracer = new DefaultTracer(NeverSampler.INSTANCE, new Random(),
|
||||
this.publisher);
|
||||
this.publisher, this.spanNamer);
|
||||
Span span = tracer.startTrace(CREATE_SIMPLE_TRACE);
|
||||
assertThat(span.isExportable(), is(false));
|
||||
}
|
||||
@@ -117,7 +120,7 @@ public class DefaultTracerTests {
|
||||
@Test
|
||||
public void exportable() {
|
||||
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
|
||||
this.publisher);
|
||||
this.publisher, this.spanNamer);
|
||||
Span span = tracer.startTrace(CREATE_SIMPLE_TRACE);
|
||||
assertThat(span.isExportable(), is(true));
|
||||
}
|
||||
@@ -125,7 +128,7 @@ public class DefaultTracerTests {
|
||||
@Test
|
||||
public void exportableInheritedFromParent() {
|
||||
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
|
||||
this.publisher);
|
||||
this.publisher, this.spanNamer);
|
||||
Span span = tracer.startTrace(CREATE_SIMPLE_TRACE, NeverSampler.INSTANCE);
|
||||
assertThat(span.isExportable(), is(false));
|
||||
Span child = tracer.joinTrace(CREATE_SIMPLE_TRACE_SPAN_NAME + "/child", span);
|
||||
@@ -135,7 +138,7 @@ public class DefaultTracerTests {
|
||||
@Test
|
||||
public void parentNotRemovedIfActiveOnJoin() {
|
||||
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
|
||||
this.publisher);
|
||||
this.publisher, this.spanNamer);
|
||||
Span parent = tracer.startTrace(CREATE_SIMPLE_TRACE);
|
||||
Span span = tracer.joinTrace(IMPORTANT_WORK_1, parent);
|
||||
tracer.close(span);
|
||||
@@ -145,7 +148,7 @@ public class DefaultTracerTests {
|
||||
@Test
|
||||
public void parentRemovedIfNotActiveOnJoin() {
|
||||
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
|
||||
this.publisher);
|
||||
this.publisher, this.spanNamer);
|
||||
Span parent = Span.builder().name(CREATE_SIMPLE_TRACE).traceId(1L).spanId(1L)
|
||||
.build();
|
||||
Span span = tracer.joinTrace(IMPORTANT_WORK_1, parent);
|
||||
@@ -156,7 +159,7 @@ public class DefaultTracerTests {
|
||||
@Test
|
||||
public void grandParentRestoredAfterAutoClose() {
|
||||
DefaultTracer tracer = new DefaultTracer(new AlwaysSampler(), new Random(),
|
||||
this.publisher);
|
||||
this.publisher, this.spanNamer);
|
||||
Span grandParent = tracer.startTrace(CREATE_SIMPLE_TRACE);
|
||||
Span parent = Span.builder().name(IMPORTANT_WORK_1).traceId(1L).spanId(1L)
|
||||
.build();
|
||||
|
||||
Reference in New Issue
Block a user