If you’re wrapping your logic in Runnable
or Callable
it’s enough to wrap those classes in their Sleuth representative.
Example for Runnable
:
Runnable runnable = new Runnable() { @Override public void run() { // do some work } @Override public String toString() { return "spanNameFromToStringMethod"; } }; // Manual `TraceRunnable` creation with explicit "calculateTax" Span name Runnable traceRunnable = new TraceRunnable(tracer, spanNamer, runnable, "calculateTax"); // Wrapping `Runnable` with `Tracer`. The Span name will be taken either from the // `@SpanName` annotation or from `toString` method Runnable traceRunnableFromTracer = tracer.wrap(runnable);
Example for Callable
:
Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { return someLogic(); } @Override public String toString() { return "spanNameFromToStringMethod"; } }; // Manual `TraceCallable` creation with explicit "calculateTax" Span name Callable<String> traceCallable = new TraceCallable<>(tracer, spanNamer, callable, "calculateTax"); // Wrapping `Callable` with `Tracer`. The Span name will be taken either from the // `@SpanName` annotation or from `toString` method Callable<String> traceCallableFromTracer = tracer.wrap(callable);
That way you will ensure that a new Span is created and closed for each execution.
We’re registering a custom HystrixConcurrencyStrategy
that wraps all Callable
instances into their Sleuth representative -
the TraceCallable
. The strategy either starts or continues a span depending on the fact whether tracing was already going
on before the Hystrix command was called. To disable the custom Hystrix Concurrency Strategy set the spring.sleuth.hystrix.strategy.enabled
to false
.
Assuming that you have the following HystrixCommand
:
HystrixCommand<String> hystrixCommand = new HystrixCommand<String>(setter) { @Override protected String run() throws Exception { return someLogic(); } };
In order to pass the tracing information you have to wrap the same logic in the Sleuth version of the HystrixCommand
which is the
TraceCommand
:
TraceCommand<String> traceCommand = new TraceCommand<String>(tracer, traceKeys, setter) { @Override public String doRun() throws Exception { return someLogic(); } };
We’re registering a custom RxJavaSchedulersHook
that wraps all Action0
instances into their Sleuth representative -
the TraceAction
. The hook either starts or continues a span depending on the fact whether tracing was already going
on before the Action was scheduled. To disable the custom RxJavaSchedulersHook set the spring.sleuth.rxjava.schedulers.hook.enabled
to false
.
You can define a list of regular expressions for thread names, for which you don’t want a Span to be created. Just provide a comma separated list
of regular expressions in the spring.sleuth.rxjava.schedulers.ignoredthreads
property.
Features from this section can be disabled by providing the spring.sleuth.web.enabled
property with value equal to false
.
Via the TraceFilter
all sampled incoming requests result in creation of a Span. That Span’s name is http:
+ the path to which
the request was sent. E.g. if the request was sent to /foo/bar
then the name will be http:/foo/bar
. You can configure which URIs you would
like to skip via the spring.sleuth.web.skipPattern
property. If you have ManagementServerProperties
on classpath then
its value of contextPath
gets appended to the provided skip pattern.
Since we want the span names to be precise we’re using a TraceHandlerInterceptor
that either wraps an
existing HandlerInterceptor
or is added directly to the list of existing HandlerInterceptors
. The
TraceHandlerInterceptor
adds a special request attribute to the given HttpServletRequest
. If the
the TraceFilter
doesn’t see this attribute set it will create a "fallback" span which is an additional
span created on the server side so that the trace is presented properly in the UI. Seeing that most likely
signifies that there is a missing instrumentation. In that case please file an issue in Spring Cloud Sleuth.
We’re injecting a RestTemplate
interceptor that ensures that all the tracing information is passed to the requests. Each time a
call is made a new Span is created. It gets closed upon receiving the response. In order to block the synchronous RestTemplate
features
just set spring.sleuth.web.client.enabled
to false
.
Important | |
---|---|
You have to register |
Important | |
---|---|
A traced version of an |
Custom instrumentation is set to create and close Spans upon sending and receiving requests. You can customize the ClientHttpRequestFactory
and the AsyncClientHttpRequestFactory
by registering your beans. Remember to use tracing compatible implementations (e.g. don’t forget to
wrap ThreadPoolTaskScheduler
in a TraceAsyncListenableTaskExecutor
). Example of custom request factories:
@EnableAutoConfiguration @Configuration public static class TestConfiguration { @Bean ClientHttpRequestFactory mySyncClientFactory() { return new MySyncClientHttpRequestFactory(); } @Bean AsyncClientHttpRequestFactory myAsyncClientFactory() { return new MyAsyncClientHttpRequestFactory(); } }
To block the AsyncRestTemplate
features set spring.sleuth.web.async.client.enabled
to false
.
To disable creation of the default TraceAsyncClientHttpRequestFactoryWrapper
set spring.sleuth.web.async.client.factory.enabled
to false
. If you don’t want to create AsyncRestClient
at all set spring.sleuth.web.async.client.template.enabled
to false
.
Sometimes you need to use multiple implementations of Asynchronous Rest Template. In the following snippet you
can see an example of how to set up such a custom AsyncRestTemplate
.
@Configuration @EnableAutoConfiguration static class Config { @Autowired Tracer tracer; @Autowired HttpTraceKeysInjector httpTraceKeysInjector; @Autowired HttpSpanInjector spanInjector; @Bean(name = "customAsyncRestTemplate") public AsyncRestTemplate traceAsyncRestTemplate(@Qualifier("customHttpRequestFactoryWrapper") TraceAsyncClientHttpRequestFactoryWrapper wrapper, ErrorParser errorParser) { return new TraceAsyncRestTemplate(wrapper, this.tracer, errorParser); } @Bean(name = "customHttpRequestFactoryWrapper") public TraceAsyncClientHttpRequestFactoryWrapper traceAsyncClientHttpRequestFactory() { return new TraceAsyncClientHttpRequestFactoryWrapper(this.tracer, this.spanInjector, asyncClientFactory(), clientHttpRequestFactory(), this.httpTraceKeysInjector); } private ClientHttpRequestFactory clientHttpRequestFactory() { ClientHttpRequestFactory clientHttpRequestFactory = new CustomClientHttpRequestFactory(); //CUSTOMIZE HERE return clientHttpRequestFactory; } private AsyncClientHttpRequestFactory asyncClientFactory() { AsyncClientHttpRequestFactory factory = new CustomAsyncClientHttpRequestFactory(); //CUSTOMIZE HERE return factory; } }
If you’re using the Traverson library
it’s enough for you to inject a RestTemplate
as a bean into your Traverson object. Since RestTemplate
is already intercepted, you will get full support of tracing in your client. Below you can find a pseudo code
of how to do that:
@Autowired RestTemplate restTemplate; Traverson traverson = new Traverson(URI.create("http://some/address"), MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8).setRestOperations(restTemplate); // use Traverson
By default Spring Cloud Sleuth provides integration with feign via the TraceFeignClientAutoConfiguration
. You can disable it entirely
by setting spring.sleuth.feign.enabled
to false. If you do so then no Feign related instrumentation will take place.
Part of Feign instrumentation is done via a FeignBeanPostProcessor
. You can disable it by providing the spring.sleuth.feign.processor.enabled
equal to false
.
If you set it like this then Spring Cloud Sleuth will not instrument any of your custom Feign components. All the default instrumentation
however will be still there.
In Spring Cloud Sleuth we’re instrumenting async related components so that the tracing information is passed between threads.
You can disable this behaviour by setting the value of spring.sleuth.async.enabled
to false
.
If you annotate your method with @Async
then we’ll automatically create a new Span with the following characteristics:
@SpanName
then the value of the annotation will be the Span’s name@SpanName
the Span name will be the annotated method nameIn Spring Cloud Sleuth we’re instrumenting scheduled method execution so that the tracing information is passed between threads. You can disable this behaviour
by setting the value of spring.sleuth.scheduled.enabled
to false
.
If you annotate your method with @Scheduled
then we’ll automatically create a new Span with the following characteristics:
If you want to skip Span creation for some @Scheduled
annotated classes you can set the
spring.sleuth.scheduled.skipPattern
with a regular expression that will match the fully qualified name of the
@Scheduled
annotated class.
Tip | |
---|---|
If you are using |
We’re providing LazyTraceExecutor
, TraceableExecutorService
and TraceableScheduledExecutorService
. Those implementations
are creating Spans each time a new task is submitted, invoked or scheduled.
Here you can see an example of how to pass tracing information with TraceableExecutorService
when working with CompletableFuture
:
CompletableFuture<Long> completableFuture = CompletableFuture.supplyAsync(() -> { // perform some logic return 1_000_000L; }, new TraceableExecutorService(executorService, // 'calculateTax' explicitly names the span - this param is optional tracer, traceKeys, spanNamer, "calculateTax"));
Important | |
---|---|
Sleuth doesn’t work with |
Sometimes you need to set up a custom instance of the AsyncExecutor
. In the following snippet you
can see an example of how to set up such a custom Executor
.
@Configuration @EnableAutoConfiguration @EnableAsync static class CustomExecutorConfig extends AsyncConfigurerSupport { @Autowired BeanFactory beanFactory; @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // CUSTOMIZE HERE executor.setCorePoolSize(7); executor.setMaxPoolSize(42); executor.setQueueCapacity(11); executor.setThreadNamePrefix("MyExecutor-"); // DON'T FORGET TO INITIALIZE executor.initialize(); return new LazyTraceExecutor(this.beanFactory, executor); } }
Spring Cloud Sleuth integrates with Spring Integration. It creates spans for publish and
subscribe events. To disable Spring Integration instrumentation, set spring.sleuth.integration.enabled
to false.
You can provide the spring.sleuth.integration.patterns
pattern to explicitly
provide the names of channels that you want to include for tracing. By default all channels
are included.
Important | |
---|---|
When using the |
We’re registering Zuul filters to propagate the tracing information (the request header is enriched with tracing data).
To disable Zuul support set the spring.sleuth.zuul.enabled
property to false
.
Sleuth works out of the box with Spring Cloud Function. Since functions
might be short living, it’s best to make the Zipkin span reporting synchronous.
Just define a Reporter<Span>
bean as presented below:
@Configuration class ReporterConfiguration { @Bean public Reporter<Span> reporter( SpanMetricReporter spanMetricReporter, ZipkinProperties zipkin, Sender sender ) { final AsyncReporter<Span> reporter = AsyncReporter.builder(sender) .queuedMaxSpans(1000) .messageTimeout(zipkin.getMessageTimeout(), TimeUnit.SECONDS) .metrics(new ReporterMetricsAdapter(spanMetricReporter)) .build(zipkin.getEncoder()); return new Reporter<Span>() { @Override public void report(Span span) { reporter.report(span); // make the reporter synchronous reporter.flush(); } }; } }