diff --git a/2.1.x/index.html b/2.1.x/index.html index 9a60ccc99..4804717dd 100644 --- a/2.1.x/index.html +++ b/2.1.x/index.html @@ -90,7 +90,7 @@ $(addBlockSwitches);
-

2.1.2.BUILD-SNAPSHOT

+

2.1.3.BUILD-SNAPSHOT

diff --git a/2.1.x/multi/multi__current_span.html b/2.1.x/multi/multi__current_span.html index 20f4099c3..e2c1d9852 100644 --- a/2.1.x/multi/multi__current_span.html +++ b/2.1.x/multi/multi__current_span.html @@ -6,13 +6,13 @@ You can use Tracer.currentSpan() to add custom tags tracer.currentSpan().context(). To get the current trace id as String you can use the traceIdString() method like this: tracer.currentSpan().context().traceIdString().

7.1 Setting a span in scope manually

When writing new instrumentation, it is important to place a span you created in scope as the current span. Not only does doing so let users access it with Tracer.currentSpan(), but it also allows customizations such as SLF4J MDC to see the current trace IDs.

Tracer.withSpanInScope(Span) facilitates this and is most conveniently employed by using the try-with-resources idiom. -Whenever external code might be invoked (such as proceeding an interceptor or otherwise), place the span in scope, as shown in the following example:

@Autowired Tracer tracer;
+Whenever external code might be invoked (such as proceeding an interceptor or otherwise), place the span in scope, as shown in the following example:

@Autowired Tracer tracer;
 
 try (SpanInScope ws = tracer.withSpanInScope(span)) {
   return inboundRequest.invoke();
 } finally { // note the scope is independent of the span
   span.finish();
-}

In edge cases, you may need to clear the current span temporarily (for example, launching a task that should not be associated with the current request). To do tso, pass null to withSpanInScope, as shown in the following example:

@Autowired Tracer tracer;
+}

In edge cases, you may need to clear the current span temporarily (for example, launching a task that should not be associated with the current request). To do tso, pass null to withSpanInScope, as shown in the following example:

@Autowired Tracer tracer;
 
 try (SpanInScope cleared = tracer.withSpanInScope(null)) {
   startBackgroundThread();
diff --git a/2.1.x/multi/multi__customizations.html b/2.1.x/multi/multi__customizations.html
index 03020042a..6f5b39373 100644
--- a/2.1.x/multi/multi__customizations.html
+++ b/2.1.x/multi/multi__customizations.html
@@ -10,14 +10,14 @@ register a bean of type brave.http.HttpSampler and
  reference the bean names via their static String NAME fields.

Check out Brave’s code to see an example of how to make a path-based sampler https://github.com/openzipkin/brave/tree/master/instrumentation/http#sampling-policy

If you want to completely rewrite the HttpTracing bean you can use the SkipPatternProvider interface to retrieve the URL Pattern for spans that should be not sampled. Below you can see -an example of usage of SkipPatternProvider inside a server side, HttpSampler.

@Configuration
+an example of usage of SkipPatternProvider inside a server side, HttpSampler.

@Configuration
 class Config {
-  @Bean(name = ServerSampler.NAME)
+  @Bean(name = ServerSampler.NAME)
   HttpSampler myHttpSampler(SkipPatternProvider provider) {
   	Pattern pattern = provider.skipPattern();
   	return new HttpSampler() {
 
-  		@Override
+  		@Override
   		public <Req> Boolean trySample(HttpAdapter<Req, ?> adapter, Req request) {
   			String url = adapter.path(request);
   			boolean shouldSkip = pattern.matcher(url).matches();
@@ -29,8 +29,8 @@ an example of usage of SkipPatternProvider inside a
   	};
   }
 }

12.2 TracingFilter

You can also modify the behavior of the TracingFilter, which is the component that is responsible for processing the input HTTP request and adding tags basing on the HTTP response. -You can customize the tags or modify the response headers by registering your own instance of the TracingFilter bean.

In the following example, we register the TracingFilter bean, add the ZIPKIN-TRACE-ID response header containing the current Span’s trace id, and add a tag with key custom and a value tag to the span.

@Component
-@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1)
+You can customize the tags or modify the response headers by registering your own instance of the TracingFilter bean.

In the following example, we register the TracingFilter bean, add the ZIPKIN-TRACE-ID response header containing the current Span’s trace id, and add a tag with key custom and a value tag to the span.

@Component
+@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1)
 class MyFilter extends GenericFilterBean {
 
 	private final Tracer tracer;
@@ -39,7 +39,7 @@ You can customize the tags or modify the response headers by registering your ow
 		this.tracer = tracer;
 	}
 
-	@Override
+	@Override
 	public void doFilter(ServletRequest request, ServletResponse response,
 			FilterChain chain) throws IOException, ServletException {
 		Span currentSpan = this.tracer.currentSpan();
@@ -61,10 +61,10 @@ There are situations in which you want to explicitly provide a different service
 To achieve that, you can pass the following property to your application to override that value (the example is for a service named myService):

spring.zipkin.service.name: myService

12.4 Customization of Reported Spans

Before reporting spans (for example, to Zipkin) you may want to modify that span in some way. You can do so by using the FinishedSpanHandler interface.

In Sleuth, we generate spans with a fixed name. Some users want to modify the name depending on values of tags. -You can implement the FinishedSpanHandler interface to alter that name.

The following example shows how to register two beans that implement FinishedSpanHandler:

@Bean
+You can implement the FinishedSpanHandler interface to alter that name.

The following example shows how to register two beans that implement FinishedSpanHandler:

@Bean
 FinishedSpanHandler handlerOne() {
 	return new FinishedSpanHandler() {
-		@Override
+		@Override
 		public boolean handle(TraceContext traceContext, MutableSpan span) {
 			span.name("foo");
 			return true; // keep this span
@@ -72,10 +72,10 @@ FinishedSpanHandler handlerOne() {
 	};
 }
 
-@Bean
+@Bean
 FinishedSpanHandler handlerTwo() {
 	return new FinishedSpanHandler() {
-		@Override
+		@Override
 		public boolean handle(TraceContext traceContext, MutableSpan span) {
 			span.name(span.name() + " bar");
 			return true; // keep this span
diff --git a/2.1.x/multi/multi__features.html b/2.1.x/multi/multi__features.html
index 7f93ddcbd..39dfbe3a8 100644
--- a/2.1.x/multi/multi__features.html
+++ b/2.1.x/multi/multi__features.html
@@ -41,7 +41,7 @@ It also includes libraries to propagate the trace context over network boundarie
 Your names have to be explicit and concrete.
 Big names lead to latency issues and sometimes even thrown exceptions.

The tracer creates and joins spans that model the latency of potentially distributed work. It can employ sampling to reduce overhead during the process, to reduce the amount of data sent to Zipkin, or both.

Spans returned by a tracer report data to Zipkin when finished or do nothing if unsampled. -After starting a span, you can annotate events of interest or add tags containing details or lookup keys.

Spans have a context that includes trace identifiers that place the span at the correct spot in the tree representing the distributed operation.

3.1.2 Local Tracing

When tracing code that never leaves your process, run it inside a scoped span.

@Autowired Tracer tracer;
+After starting a span, you can annotate events of interest or add tags containing details or lookup keys.

Spans have a context that includes trace identifiers that place the span at the correct spot in the tree representing the distributed operation.

3.1.2 Local Tracing

When tracing code that never leaves your process, run it inside a scoped span.

@Autowired Tracer tracer;
 
 // Start a new trace or a span within an existing trace representing an operation
 ScopedSpan span = tracer.startScopedSpan("encode");
@@ -53,7 +53,7 @@ ScopedSpan span = tracer.startScopedSpan(throw e;
 } finally {
   span.finish(); // always finish the span
-}

When you need more features, or finer control, use the Span type:

@Autowired Tracer tracer;
+}

When you need more features, or finer control, use the Span type:

@Autowired Tracer tracer;
 
 // Start a new trace or a span within an existing trace representing an operation
 Span span = tracer.nextSpan().name("encode").start();
@@ -75,19 +75,19 @@ The former is simpler to understand and test and does not tempt users with span
   callback.request(request, span);
 }

3.1.4 Implicitly Looking up the Current Span

Sometimes, you do not know if a trace is in progress or not, and you do not want users to do null checks. brave.CurrentSpanCustomizer handles this problem by adding data to any span that’s in progress or drops, as shown in the following example:

Ex.

// The user code can then inject this without a chance of it being null.
-@Autowired SpanCustomizer span;
+@Autowired SpanCustomizer span;
 
 void userCode() {
   span.annotate("tx.started");
   ...
-}

3.1.5 RPC tracing

[Tip]Tip

Check for instrumentation written here and Zipkin’s list before rolling your own RPC instrumentation.

RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation.

The following example shows how to add a client span:

@Autowired Tracing tracing;
-@Autowired Tracer tracer;
+}

3.1.5 RPC tracing

[Tip]Tip

Check for instrumentation written here and Zipkin’s list before rolling your own RPC instrumentation.

RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation.

The following example shows how to add a client span:

@Autowired Tracing tracing;
+@Autowired Tracer tracer;
 
 // before you send a request, add metadata that describes the operation
 span = tracer.nextSpan().name(service + "/" + method).kind(CLIENT);
 span.tag("myrpc.version", "1.0.0");
 span.remoteServiceName("backend");
-span.remoteIpAndPort("172.3.4.1", 8108);
+span.remoteIpAndPort("172.3.4.1", 8108);
 
 // Add the trace context to the request, so it can be propagated in-band
 tracing.propagation().injector(Request::addHeader)
@@ -105,8 +105,8 @@ span.error(exception);
 span.finish();

One-Way tracing

Sometimes, you need to model an asynchronous operation where there is a request but no response. In normal RPC tracing, you use span.finish() to indicate that the response was received. In one-way tracing, you use -span.flush() instead, as you do not expect a response.

The following example shows how a client might model a one-way operation:

@Autowired Tracing tracing;
-@Autowired Tracer tracer;
+span.flush() instead, as you do not expect a response.

The following example shows how a client might model a one-way operation:

@Autowired Tracing tracing;
+@Autowired Tracer tracer;
 
 // start a new span representing a client request
 oneWaySend = tracer.nextSpan().name(service + "/" + method).kind(CLIENT);
@@ -119,8 +119,8 @@ tracing.propagation().injector(Request::addHeader)
 request.execute();
 
 // start the client side and flush instead of finish
-oneWaySend.start().flush();

The following example shows how a server might handle a one-way operation:

@Autowired Tracing tracing;
-@Autowired Tracer tracer;
+oneWaySend.start().flush();

The following example shows how a server might handle a one-way operation:

@Autowired Tracing tracing;
+@Autowired Tracer tracer;
 
 // pull the context out of the incoming request
 extractor = tracing.propagation().extractor(Request::getHeader);
diff --git a/2.1.x/multi/multi__integrations.html b/2.1.x/multi/multi__integrations.html
index 0b4fd0e4a..e810833df 100644
--- a/2.1.x/multi/multi__integrations.html
+++ b/2.1.x/multi/multi__integrations.html
@@ -3,12 +3,12 @@
    15. Integrations

15. Integrations

15.1 OpenTracing

Spring Cloud Sleuth is compatible with OpenTracing. If you have OpenTracing on the classpath, we automatically register the OpenTracing Tracer bean. If you wish to disable this, set spring.sleuth.opentracing.enabled to false

15.2 Runnable and Callable

If you wrap your logic in Runnable or Callable, you can wrap those classes in their Sleuth representative, as shown in the following example for Runnable:

Runnable runnable = new Runnable() {
-	@Override
+	@Override
 	public void run() {
 		// do some work
 	}
 
-	@Override
+	@Override
 	public String toString() {
 		return "spanNameFromToStringMethod";
 	}
@@ -20,12 +20,12 @@ Runnable traceRunnable = // in the thread of `Runnable`
 Runnable traceRunnableFromTracer = this.tracing.currentTraceContext()
 		.wrap(runnable);

The following example shows how to do so for Callable:

Callable<String> callable = new Callable<String>() {
-	@Override
+	@Override
 	public String call() throws Exception {
 		return someLogic();
 	}
 
-	@Override
+	@Override
 	public String toString() {
 		return "spanNameFromToStringMethod";
 	}
@@ -39,13 +39,13 @@ Callable<String> traceCallableFromTracer = 

15.3 Hystrix

15.3.1 Custom Concurrency Strategy

We register a custom HystrixConcurrencyStrategy called TraceCallable that wraps all Callable instances in their Sleuth representative. The strategy either starts or continues a span, depending on 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.

15.3.2 Manual Command setting

Assume that you have the following HystrixCommand:

HystrixCommand<String> hystrixCommand = new HystrixCommand<String>(setter) {
-	@Override
+	@Override
 	protected String run() throws Exception {
 		return someLogic();
 	}
 };

To pass the tracing information, you have to wrap the same logic in the Sleuth version of the HystrixCommand, which is called TraceCommand, as shown in the following example:

TraceCommand<String> traceCommand = new TraceCommand<String>(tracer, setter) {
-	@Override
+	@Override
 	public String doRun() throws Exception {
 		return someLogic();
 	}
@@ -88,11 +88,11 @@ Then we instrument it.

To block the TraceAsyncClientHttpRequestFactoryWrapper, set spring.sleuth.web.async.client.factory.enabled to false. If you do not want to create AsyncRestClient at all, set spring.sleuth.web.async.client.template.enabled to false.

Multiple Asynchronous Rest Templates

Sometimes you need to use multiple implementations of the Asynchronous Rest Template. -In the following snippet, you can see an example of how to set up such a custom AsyncRestTemplate:

@Configuration
-@EnableAutoConfiguration
+In the following snippet, you can see an example of how to set up such a custom AsyncRestTemplate:

@Configuration
+@EnableAutoConfiguration
 static class Config {
 
-	@Bean(name = "customAsyncRestTemplate")
+	@Bean(name = "customAsyncRestTemplate")
 	public AsyncRestTemplate traceAsyncRestTemplate() {
 		return new AsyncRestTemplate(asyncClientFactory(),
 				clientHttpRequestFactory());
@@ -113,7 +113,7 @@ In the following snippet, you can see an example of how to set up such a custom
 }

15.6.3 WebClient

We inject a ExchangeFilterFunction implementation that creates a span and, through on-success and on-error callbacks, takes care of closing client-side spans.

To block this feature, set spring.sleuth.web.client.enabled to false.

[Important]Important

You have to register WebClient as a bean so that the tracing instrumentation gets applied. If you create a WebClient instance with a new keyword, the instrumentation does NOT work.

15.6.4 Traverson

If you use the Traverson library, you can inject a RestTemplate as a bean into your Traverson object. Since RestTemplate is already intercepted, you get full support for tracing in your client. The following pseudo code -shows how to do that:

@Autowired RestTemplate restTemplate;
+shows 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);
@@ -138,30 +138,30 @@ You can disable this behavior by setting the value of spri
 If you use spring-cloud-sleuth-stream and spring-cloud-netflix-hystrix-stream together, a span is created for each Hystrix metrics and sent to Zipkin.
 This behavior may be annoying. That’s why, by default, spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask.

15.9.3 Executor, ExecutorService, and ScheduledExecutorService

We provide LazyTraceExecutor, TraceableExecutorService, and TraceableScheduledExecutorService. Those implementations create spans each time a new task is submitted, invoked, or scheduled.

The following example shows how to pass tracing information with TraceableExecutorService when working with CompletableFuture:

CompletableFuture<Long> completableFuture = CompletableFuture.supplyAsync(() -> {
 	// perform some logic
-	return 1_000_000L;
+	return 1_000_000L;
 }, new TraceableExecutorService(beanFactory, executorService,
 		// 'calculateTax' explicitly names the span - this param is optional
 		"calculateTax"));
[Important]Important

Sleuth does not work with parallelStream() out of the box. If you want to have the tracing information propagated through the stream, you have to use the approach with supplyAsync(...), as shown earlier.

If there are beans that implement the Executor interface that you would like to exclude from span creation, you can use the spring.sleuth.async.ignored-beans property where you can provide a list of bean names.

Customization of Executors

Sometimes, you need to set up a custom instance of the AsyncExecutor. -The following example shows how to set up such a custom Executor:

@Configuration
-@EnableAutoConfiguration
-@EnableAsync
+The following example shows how to set up such a custom Executor:

@Configuration
+@EnableAutoConfiguration
+@EnableAsync
 // add the infrastructure role to ensure that the bean gets auto-proxied
-@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
+@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 static class CustomExecutorConfig extends AsyncConfigurerSupport {
 
-	@Autowired
+	@Autowired
 	BeanFactory beanFactory;
 
-	@Override
+	@Override
 	public Executor getAsyncExecutor() {
 		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
 		// CUSTOMIZE HERE
-		executor.setCorePoolSize(7);
-		executor.setMaxPoolSize(42);
-		executor.setQueueCapacity(11);
+		executor.setCorePoolSize(7);
+		executor.setMaxPoolSize(42);
+		executor.setQueueCapacity(11);
 		executor.setThreadNamePrefix("MyExecutor-");
 		// DON'T FORGET TO INITIALIZE
 		executor.initialize();
diff --git a/2.1.x/multi/multi__introduction.html b/2.1.x/multi/multi__introduction.html
index 86b143d57..b0d5b28ce 100644
--- a/2.1.x/multi/multi__introduction.html
+++ b/2.1.x/multi/multi__introduction.html
@@ -53,7 +53,7 @@ An example from Kibana would resemble the following image:

JSON Logback with Logstash

Often, you do not want to store your logs in a text file but in a JSON file that Logstash can immediately pick. -To do so, you have to do the following (for readability, we pass the dependencies in the groupId:artifactId:version notation).

Dependencies Setup

  1. Ensure that Logback is on the classpath (ch.qos.logback:logback-core).
  2. Add Logstash Logback encode. For example, to use version 4.6, add net.logstash.logback:logstash-logback-encoder:4.6.

Logback Setup

Consider the following example of a Logback configuration file (named logback-spring.xml).

<?xml version="1.0" encoding="UTF-8"?>
+To do so, you have to do the following (for readability, we pass the dependencies in the groupId:artifactId:version notation).

Dependencies Setup

  1. Ensure that Logback is on the classpath (ch.qos.logback:logback-core).
  2. Add Logstash Logback encode. For example, to use version 4.6, add net.logstash.logback:logstash-logback-encoder:4.6.

Logback Setup

Consider the following example of a Logback configuration file (named logback-spring.xml).

<?xml version="1.0" encoding="UTF-8"?>
 <configuration>
 	<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
 	​
@@ -244,15 +244,15 @@ dependencies {
 

1

We recommend that you add the dependency management through the Spring BOM so that you need not manage versions yourself.

2

Add the dependency to spring-cloud-starter-zipkin. That way, all nested dependencies get downloaded.

3

To automatically configure RabbitMQ, add the spring-rabbit dependency.

1.4 Overriding the auto-configuration of Zipkin

Spring Cloud Sleuth supports sending traces to multiple tracing systems as of version 2.1.0. In order to get this to work, every tracing system needs to have a Reporter<Span> and Sender. If you want to override the provided beans you need to give them a specific name. -To do this you can use respectively ZipkinAutoConfiguration.REPORTER_BEAN_NAME and ZipkinAutoConfiguration.SENDER_BEAN_NAME.

@Configuration
+To do this you can use respectively ZipkinAutoConfiguration.REPORTER_BEAN_NAME and ZipkinAutoConfiguration.SENDER_BEAN_NAME.

@Configuration
 protected static class MyConfig {
 
-	@Bean(ZipkinAutoConfiguration.REPORTER_BEAN_NAME)
+	@Bean(ZipkinAutoConfiguration.REPORTER_BEAN_NAME)
 	Reporter<zipkin2.Span> myReporter() {
 		return AsyncReporter.create(mySender());
 	}
 
-	@Bean(ZipkinAutoConfiguration.SENDER_BEAN_NAME)
+	@Bean(ZipkinAutoConfiguration.SENDER_BEAN_NAME)
 	MySender mySender() {
 		return new MySender();
 	}
@@ -265,22 +265,22 @@ To do this you can use respectively ZipkinAutoConfiguratio
 			return this.spanSent;
 		}
 
-		@Override
+		@Override
 		public Encoding encoding() {
 			return Encoding.JSON;
 		}
 
-		@Override
+		@Override
 		public int messageMaxBytes() {
 			return Integer.MAX_VALUE;
 		}
 
-		@Override
+		@Override
 		public int messageSizeInBytes(List<byte[]> encodedSpans) {
 			return encoding().listSizeInBytes(encodedSpans);
 		}
 
-		@Override
+		@Override
 		public Call<Void> sendSpans(List<byte[]> encodedSpans) {
 			this.spanSent = true;
 			return Call.create(null);
diff --git a/2.1.x/multi/multi__managing_spans_with_annotations.html b/2.1.x/multi/multi__managing_spans_with_annotations.html
index cd81acde9..bb19500ba 100644
--- a/2.1.x/multi/multi__managing_spans_with_annotations.html
+++ b/2.1.x/multi/multi__managing_spans_with_annotations.html
@@ -5,23 +5,23 @@ Doing so lets Sleuth change its core API to create less impact to user code.
  • Collaboration with runtime generated code. With libraries such as Spring Data and Feign, the implementations of interfaces are generated at runtime. Consequently, span wrapping of objects was tedious. Now you can provide annotations over interfaces and the arguments of those interfaces.
  • 11.2 Creating New Spans

    If you do not want to create local spans manually, you can use the @NewSpan annotation. -Also, we provide the @SpanTag annotation to add tags in an automated fashion.

    Now we can consider some examples of usage.

    @NewSpan
    -void testMethod();

    Annotating the method without any parameter leads to creating a new span whose name equals the annotated method name.

    @NewSpan("customNameOnTestMethod4")
    +Also, we provide the @SpanTag annotation to add tags in an automated fashion.

    Now we can consider some examples of usage.

    @NewSpan
    +void testMethod();

    Annotating the method without any parameter leads to creating a new span whose name equals the annotated method name.

    @NewSpan("customNameOnTestMethod4")
     void testMethod4();

    If you provide the value in the annotation (either directly or by setting the name parameter), the created span has the provided value as the name.

    // method declaration
    -@NewSpan(name = "customNameOnTestMethod5")
    -void testMethod5(@SpanTag("testTag") String param);
    +@NewSpan(name = "customNameOnTestMethod5")
    +void testMethod5(@SpanTag("testTag") String param);
     
     // and method execution
     this.testBean.testMethod5("test");

    You can combine both the name and a tag. Let’s focus on the latter. In this case, the value of the annotated method’s parameter runtime value becomes the value of the tag. -In our sample, the tag key is testTag, and the tag value is test.

    @NewSpan(name = "customNameOnTestMethod3")
    -@Override
    +In our sample, the tag key is testTag, and the tag value is test.

    @NewSpan(name = "customNameOnTestMethod3")
    +@Override
     public void testMethod3() {
     }

    You can place the @NewSpan annotation on both the class and an interface. If you override the interface’s method and provide a different value for the @NewSpan annotation, the most concrete one wins (in this case customNameOnTestMethod3 is set).

    11.3 Continuing Spans

    If you want to add tags and annotations to an existing span, you can use the @ContinueSpan annotation, as shown in the following example:

    // method declaration
    -@ContinueSpan(log = "testMethod11")
    -void testMethod11(@SpanTag("testTag11") String param);
    +@ContinueSpan(log = "testMethod11")
    +void testMethod11(@SpanTag("testTag11") String param);
     
     // method execution
     this.testBean.testMethod11("test");
    @@ -30,16 +30,16 @@ The precedence is as follows:

    11.4.1 Custom extractor

    The value of the tag for the following method is computed by an implementation of TagValueResolver interface. -Its class name has to be passed as the value of the resolver attribute.

    Consider the following annotated method:

    @NewSpan
    +Its class name has to be passed as the value of the resolver attribute.

    Consider the following annotated method:

    @NewSpan
     public void getAnnotationForTagValueResolver(
    -		@SpanTag(key = "test", resolver = TagValueResolver.class) String test) {
    -}

    Now further consider the following TagValueResolver bean implementation:

    @Bean(name = "myCustomTagValueResolver")
    +		@SpanTag(key = "test", resolver = TagValueResolver.class) String test) {
    +}

    Now further consider the following TagValueResolver bean implementation:

    @Bean(name = "myCustomTagValueResolver")
     public TagValueResolver tagValueResolver() {
     	return parameter -> "Value from myCustomTagValueResolver";
    -}

    The two preceding examples lead to setting a tag value equal to Value from myCustomTagValueResolver.

    11.4.2 Resolving Expressions for a Value

    Consider the following annotated method:

    @NewSpan
    +}

    The two preceding examples lead to setting a tag value equal to Value from myCustomTagValueResolver.

    11.4.2 Resolving Expressions for a Value

    Consider the following annotated method:

    @NewSpan
     public void getAnnotationForTagValueExpression(
    -		@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) {
    +		@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) {
     }

    No custom implementation of a TagValueExpressionResolver leads to evaluation of the SPEL expression, and a tag with a value of 4 characters is set on the span. -If you want to use some other expression resolution mechanism, you can create your own implementation of the bean.

    11.4.3 Using the toString() method

    Consider the following annotated method:

    @NewSpan
    -public void getAnnotationForArgumentToString(@SpanTag("test") Long param) {
    +If you want to use some other expression resolution mechanism, you can create your own implementation of the bean.

    11.4.3 Using the toString() method

    Consider the following annotated method:

    @NewSpan
    +public void getAnnotationForArgumentToString(@SpanTag("test") Long param) {
     }

    Running the preceding method with a value of 15 leads to setting a tag with a String value of "15".

    \ No newline at end of file diff --git a/2.1.x/multi/multi__naming_spans.html b/2.1.x/multi/multi__naming_spans.html index c1d4e5c3b..ceca5ae7e 100644 --- a/2.1.x/multi/multi__naming_spans.html +++ b/2.1.x/multi/multi__naming_spans.html @@ -1,10 +1,10 @@ 10. Naming spans

    10. Naming spans

    Picking a span name is not a trivial task. A span name should depict an operation name. -The name should be low cardinality, so it should not include identifiers.

    Since there is a lot of instrumentation going on, some span names are artificial:

    • controller-method-name when received by a Controller with a method name of controllerMethodName
    • async for asynchronous operations done with wrapped Callable and Runnable interfaces.
    • Methods annotated with @Scheduled return the simple name of the class.

    Fortunately, for asynchronous processing, you can provide explicit naming.

    10.1 @SpanName Annotation

    You can name the span explicitly by using the @SpanName annotation, as shown in the following example:

    	@SpanName("calculateTax")
    +The name should be low cardinality, so it should not include identifiers.

    Since there is a lot of instrumentation going on, some span names are artificial:

    • controller-method-name when received by a Controller with a method name of controllerMethodName
    • async for asynchronous operations done with wrapped Callable and Runnable interfaces.
    • Methods annotated with @Scheduled return the simple name of the class.

    Fortunately, for asynchronous processing, you can provide explicit naming.

    10.1 @SpanName Annotation

    You can name the span explicitly by using the @SpanName annotation, as shown in the following example:

    	@SpanName("calculateTax")
     	class TaxCountingRunnable implements Runnable {
     
    -		@Override
    +		@Override
     		public void run() {
     			// perform logic
     		}
    @@ -19,12 +19,12 @@ future.get();
    < Typically, one creates an anonymous instance of those classes. You cannot annotate such classes. To overcome that limitation, if there is no @SpanName annotation present, we check whether the class has a custom implementation of the toString() method.

    Running such code leads to creating a span named calculateTax, as shown in the following example:

    Runnable runnable = new TraceRunnable(this.tracing, spanNamer, new Runnable() {
    -	@Override
    +	@Override
     	public void run() {
     		// perform logic
     	}
     
    -	@Override
    +	@Override
     	public String toString() {
     		return "calculateTax";
     	}
    diff --git a/2.1.x/multi/multi__propagation.html b/2.1.x/multi/multi__propagation.html
    index edb8a4310..da57bc208 100644
    --- a/2.1.x/multi/multi__propagation.html
    +++ b/2.1.x/multi/multi__propagation.html
    @@ -16,14 +16,14 @@ The most common propagation approach is to copy a trace context from a client by
     │ └──────────────┘ │          └───────────────────┘        │ └──────────────┘ │
     │                  │                                       │                  │
     └──────────────────┘                                       └──────────────────┘

    The names above are from B3 Propagation, which is built-in to Brave and has implementations in many languages and frameworks.

    Most users use a framework interceptor to automate propagation. -The next two examples show how that might work for a client and a server.

    The following example shows how client-side propagation might work:

    @Autowired Tracing tracing;
    +The next two examples show how that might work for a client and a server.

    The following example shows how client-side propagation might work:

    @Autowired Tracing tracing;
     
     // configure a function that injects a trace context into a request
     injector = tracing.propagation().injector(Request.Builder::addHeader);
     
     // before a request is sent, add the current span's context to it
    -injector.inject(span.context(), request);

    The following example shows how server-side propagation might work:

    @Autowired Tracing tracing;
    -@Autowired Tracer tracer;
    +injector.inject(span.context(), request);

    The following example shows how server-side propagation might work:

    @Autowired Tracing tracing;
    +@Autowired Tracer tracer;
     
     // configure a function that extracts the trace context from a request
     extractor = tracing.propagation().extractor(Request::getHeader);
    diff --git a/2.1.x/multi/multi__sampling.html b/2.1.x/multi/multi__sampling.html
    index 5eed9a2cf..4f3032030 100644
    --- a/2.1.x/multi/multi__sampling.html
    +++ b/2.1.x/multi/multi__sampling.html
    @@ -3,12 +3,12 @@
        4. Sampling

    4. Sampling

    Sampling may be employed to reduce the data collected and reported out of process. When a span is not sampled, it adds no overhead (a noop).

    Sampling is an up-front decision, meaning that the decision to report data is made at the first operation in a trace and that decision is propagated downstream.

    By default, a global sampler applies a single rate to all traced operations. Tracer.Builder.sampler controls this setting, and it defaults to tracing every request.

    4.1 Declarative sampling

    Some applications need to sample based on the type or annotations of a java method.

    Most users use a framework interceptor to automate this sort of policy. -The following example shows how that might work internally:

    @Autowired Tracer tracer;
    +The following example shows how that might work internally:

    @Autowired Tracer tracer;
     
     // derives a sample rate from an annotation on a java method
     DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sampleRate);
     
    -@Around("@annotation(traced)")
    +@Around("@annotation(traced)")
     public Object traceThing(ProceedingJoinPoint pjp, Traced traced) throws Throwable {
       // When there is no trace in progress, this decides using an annotation
       Sampler decideUsingAnnotation = declarativeSampler.toSampler(traced);
    @@ -26,12 +26,12 @@ DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sam
       }
     }

    4.2 Custom sampling

    Depending on what the operation is, you may want to apply different policies. For example, you might not want to trace requests to static resources such as images, or you might want to trace all requests to a new api.

    Most users use a framework interceptor to automate this sort of policy. -The following example shows how that might work internally:

    @Autowired Tracer tracer;
    -@Autowired Sampler fallback;
    +The following example shows how that might work internally:

    @Autowired Tracer tracer;
    +@Autowired Sampler fallback;
     
     Span nextSpan(final Request input) {
       Sampler requestBased = Sampler() {
    -    @Override public boolean isSampled(long traceId) {
    +    @Override public boolean isSampled(long traceId) {
           if (input.url().startsWith("/experimental")) {
             return true;
           } else if (input.url().startsWith("/static")) {
    @@ -46,7 +46,7 @@ That means that traces appear in logs but not in any remote store.
     For testing the default is often enough, and it probably is all you need if you use only the logs (for example, with an ELK aggregator).
     If you export span data to Zipkin, there is also an Sampler.ALWAYS_SAMPLE setting that exports everything and a ProbabilityBasedSampler setting that samples a fixed fraction of spans.

    [Note]Note

    The ProbabilityBasedSampler is the default if you use spring-cloud-sleuth-zipkin. You can configure the exports by setting spring.sleuth.sampler.probability. -The passed value needs to be a double from 0.0 to 1.0.

    A sampler can be installed by creating a bean definition, as shown in the following example:

    @Bean
    +The passed value needs to be a double from 0.0 to 1.0.

    A sampler can be installed by creating a bean definition, as shown in the following example:

    @Bean
     public Sampler defaultSampler() {
     	return Sampler.ALWAYS_SAMPLE;
     }
    [Tip]Tip

    You can set the HTTP header X-B3-Flags to 1, or, when doing messaging, you can set the spanFlags header to 1. diff --git a/2.1.x/multi/multi__sending_spans_to_zipkin.html b/2.1.x/multi/multi__sending_spans_to_zipkin.html index f89d22c9e..c80f33fbf 100644 --- a/2.1.x/multi/multi__sending_spans_to_zipkin.html +++ b/2.1.x/multi/multi__sending_spans_to_zipkin.html @@ -2,25 +2,25 @@ 13. Sending Spans to Zipkin

    13. Sending Spans to Zipkin

    By default, if you add spring-cloud-starter-zipkin as a dependency to your project, when the span is closed, it is sent to Zipkin over HTTP. The communication is asynchronous. -You can configure the URL by setting the spring.zipkin.baseUrl property, as follows:

    spring.zipkin.baseUrl: https://192.168.99.100:9411/

    If you want to find Zipkin through service discovery, you can pass the Zipkin’s service ID inside the URL, as shown in the following example for zipkinserver service ID:

    spring.zipkin.baseUrl: http://zipkinserver/

    To disable this feature just set spring.zipkin.discoveryClientEnabled to `false.

    When the Discovery Client feature is enabled, Sleuth uses +You can configure the URL by setting the spring.zipkin.baseUrl property, as follows:

    spring.zipkin.baseUrl: https://192.168.99.100:9411/

    If you want to find Zipkin through service discovery, you can pass the Zipkin’s service ID inside the URL, as shown in the following example for zipkinserver service ID:

    spring.zipkin.baseUrl: http://zipkinserver/

    To disable this feature just set spring.zipkin.discoveryClientEnabled to `false.

    When the Discovery Client feature is enabled, Sleuth uses LoadBalancerClient to find the URL of the Zipkin Server. It means that you can set up the load balancing configuration e.g. via Ribbon.

    zipkinserver:
       ribbon:
         ListOfServers: host1,host2

    If you have web, rabbit, or kafka together on the classpath, you might need to pick the means by which you would like to send spans to zipkin. To do so, set web, rabbit, or kafka to the spring.zipkin.sender.type property. The following example shows setting the sender type for web:

    spring.zipkin.sender.type: web

    To customize the RestTemplate that sends spans to Zipkin via HTTP, you can register -the ZipkinRestTemplateCustomizer bean.

    @Configuration
    +the ZipkinRestTemplateCustomizer bean.

    @Configuration
     class MyConfig {
    -	@Bean ZipkinRestTemplateCustomizer myCustomizer() {
    +	@Bean ZipkinRestTemplateCustomizer myCustomizer() {
     		return new ZipkinRestTemplateCustomizer() {
    -			@Override
    +			@Override
     			void customize(RestTemplate restTemplate) {
     				// customize the RestTemplate
     			}
     		};
     	}
     }

    If, however, you would like to control the full process of creating the RestTemplate -object, you will have to create a bean of zipkin2.reporter.Sender type.

    	@Bean Sender myRestTemplateSender(ZipkinProperties zipkin,
    +object, you will have to create a bean of zipkin2.reporter.Sender type.

    	@Bean Sender myRestTemplateSender(ZipkinProperties zipkin,
     			ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer) {
     		RestTemplate restTemplate = mySuperCustomRestTemplate();
     		zipkinRestTemplateCustomizer.customize(restTemplate);
    diff --git a/2.1.x/multi/multi_pr01.html b/2.1.x/multi/multi_pr01.html
    index 1f67a9b5b..98b2c57e2 100644
    --- a/2.1.x/multi/multi_pr01.html
    +++ b/2.1.x/multi/multi_pr01.html
    @@ -1,3 +1,3 @@
     
           
    -   

    2.1.2.BUILD-SNAPSHOT

    \ No newline at end of file +

    2.1.3.BUILD-SNAPSHOT

    \ No newline at end of file diff --git a/2.1.x/single/spring-cloud-sleuth.html b/2.1.x/single/spring-cloud-sleuth.html index 25177a571..a62d7ca6c 100644 --- a/2.1.x/single/spring-cloud-sleuth.html +++ b/2.1.x/single/spring-cloud-sleuth.html @@ -1,6 +1,6 @@ - Spring Cloud Sleuth

    Spring Cloud Sleuth

    Adrian Cole, Spencer Gibb, Marcin Grzejszczak, Dave Syer, Jay Bryant

    Table of Contents

    1. Introduction
    1.1. Terminology
    1.2. Purpose
    1.2.1. Distributed Tracing with Zipkin
    1.2.2. Visualizing errors
    1.2.3. Distributed Tracing with Brave
    1.2.4. Live examples
    1.2.5. Log correlation
    JSON Logback with Logstash
    1.2.6. Propagating Span Context
    Baggage versus Span Tags
    1.3. Adding Sleuth to the Project
    1.3.1. Only Sleuth (log correlation)
    1.3.2. Sleuth with Zipkin via HTTP
    1.3.3. Sleuth with Zipkin over RabbitMQ or Kafka
    1.4. Overriding the auto-configuration of Zipkin
    2. Additional Resources
    3. Features
    3.1. Introduction to Brave
    3.1.1. Tracing
    3.1.2. Local Tracing
    3.1.3. Customizing Spans
    3.1.4. Implicitly Looking up the Current Span
    3.1.5. RPC tracing
    One-Way tracing
    4. Sampling
    4.1. Declarative sampling
    4.2. Custom sampling
    4.3. Sampling in Spring Cloud Sleuth
    5. Propagation
    5.1. Propagating extra fields
    5.1.1. Prefixed fields
    5.1.2. Extracting a Propagated Context
    5.1.3. Sharing span IDs between Client and Server
    5.1.4. Implementing Propagation
    6. Current Tracing Component
    7. Current Span
    7.1. Setting a span in scope manually
    8. Instrumentation
    9. Span lifecycle
    9.1. Creating and finishing spans
    9.2. Continuing Spans
    9.3. Creating a Span with an explicit Parent
    10. Naming spans
    10.1. @SpanName Annotation
    10.2. toString() method
    11. Managing Spans with Annotations
    11.1. Rationale
    11.2. Creating New Spans
    11.3. Continuing Spans
    11.4. Advanced Tag Setting
    11.4.1. Custom extractor
    11.4.2. Resolving Expressions for a Value
    11.4.3. Using the toString() method
    12. Customizations
    12.1. HTTP
    12.2. TracingFilter
    12.3. Custom service name
    12.4. Customization of Reported Spans
    12.5. Host Locator
    13. Sending Spans to Zipkin
    14. Zipkin Stream Span Consumer
    15. Integrations
    15.1. OpenTracing
    15.2. Runnable and Callable
    15.3. Hystrix
    15.3.1. Custom Concurrency Strategy
    15.3.2. Manual Command setting
    15.4. RxJava
    15.5. HTTP integration
    15.5.1. HTTP Filter
    15.5.2. HandlerInterceptor
    15.5.3. Async Servlet support
    15.5.4. WebFlux support
    15.5.5. Dubbo RPC support
    15.6. HTTP Client Integration
    15.6.1. Synchronous Rest Template
    15.6.2. Asynchronous Rest Template
    Multiple Asynchronous Rest Templates
    15.6.3. WebClient
    15.6.4. Traverson
    15.6.5. Apache HttpClientBuilder and HttpAsyncClientBuilder
    15.6.6. Netty HttpClient
    15.6.7. UserInfoRestTemplateCustomizer
    15.7. Feign
    15.8. gRPC
    15.8.1. Variant 1
    Dependencies
    Server Instrumentation
    Client Instrumentation
    15.8.2. Variant 2
    15.9. Asynchronous Communication
    15.9.1. @Async Annotated methods
    15.9.2. @Scheduled Annotated Methods
    15.9.3. Executor, ExecutorService, and ScheduledExecutorService
    Customization of Executors
    15.10. Messaging
    15.10.1. Spring Integration and Spring Cloud Stream
    15.10.2. Spring RabbitMq
    15.10.3. Spring Kafka
    15.10.4. Spring JMS
    15.11. Zuul
    16. Running examples

    2.1.2.BUILD-SNAPSHOT

    1. Introduction

    Spring Cloud Sleuth implements a distributed tracing solution for Spring Cloud.

    1.1 Terminology

    Spring Cloud Sleuth borrows Dapper’s terminology.

    Span: The basic unit of work. For example, sending an RPC is a new span, as is sending a response to an RPC. + Spring Cloud Sleuth

    Spring Cloud Sleuth

    Adrian Cole, Spencer Gibb, Marcin Grzejszczak, Dave Syer, Jay Bryant

    Table of Contents

    1. Introduction
    1.1. Terminology
    1.2. Purpose
    1.2.1. Distributed Tracing with Zipkin
    1.2.2. Visualizing errors
    1.2.3. Distributed Tracing with Brave
    1.2.4. Live examples
    1.2.5. Log correlation
    JSON Logback with Logstash
    1.2.6. Propagating Span Context
    Baggage versus Span Tags
    1.3. Adding Sleuth to the Project
    1.3.1. Only Sleuth (log correlation)
    1.3.2. Sleuth with Zipkin via HTTP
    1.3.3. Sleuth with Zipkin over RabbitMQ or Kafka
    1.4. Overriding the auto-configuration of Zipkin
    2. Additional Resources
    3. Features
    3.1. Introduction to Brave
    3.1.1. Tracing
    3.1.2. Local Tracing
    3.1.3. Customizing Spans
    3.1.4. Implicitly Looking up the Current Span
    3.1.5. RPC tracing
    One-Way tracing
    4. Sampling
    4.1. Declarative sampling
    4.2. Custom sampling
    4.3. Sampling in Spring Cloud Sleuth
    5. Propagation
    5.1. Propagating extra fields
    5.1.1. Prefixed fields
    5.1.2. Extracting a Propagated Context
    5.1.3. Sharing span IDs between Client and Server
    5.1.4. Implementing Propagation
    6. Current Tracing Component
    7. Current Span
    7.1. Setting a span in scope manually
    8. Instrumentation
    9. Span lifecycle
    9.1. Creating and finishing spans
    9.2. Continuing Spans
    9.3. Creating a Span with an explicit Parent
    10. Naming spans
    10.1. @SpanName Annotation
    10.2. toString() method
    11. Managing Spans with Annotations
    11.1. Rationale
    11.2. Creating New Spans
    11.3. Continuing Spans
    11.4. Advanced Tag Setting
    11.4.1. Custom extractor
    11.4.2. Resolving Expressions for a Value
    11.4.3. Using the toString() method
    12. Customizations
    12.1. HTTP
    12.2. TracingFilter
    12.3. Custom service name
    12.4. Customization of Reported Spans
    12.5. Host Locator
    13. Sending Spans to Zipkin
    14. Zipkin Stream Span Consumer
    15. Integrations
    15.1. OpenTracing
    15.2. Runnable and Callable
    15.3. Hystrix
    15.3.1. Custom Concurrency Strategy
    15.3.2. Manual Command setting
    15.4. RxJava
    15.5. HTTP integration
    15.5.1. HTTP Filter
    15.5.2. HandlerInterceptor
    15.5.3. Async Servlet support
    15.5.4. WebFlux support
    15.5.5. Dubbo RPC support
    15.6. HTTP Client Integration
    15.6.1. Synchronous Rest Template
    15.6.2. Asynchronous Rest Template
    Multiple Asynchronous Rest Templates
    15.6.3. WebClient
    15.6.4. Traverson
    15.6.5. Apache HttpClientBuilder and HttpAsyncClientBuilder
    15.6.6. Netty HttpClient
    15.6.7. UserInfoRestTemplateCustomizer
    15.7. Feign
    15.8. gRPC
    15.8.1. Variant 1
    Dependencies
    Server Instrumentation
    Client Instrumentation
    15.8.2. Variant 2
    15.9. Asynchronous Communication
    15.9.1. @Async Annotated methods
    15.9.2. @Scheduled Annotated Methods
    15.9.3. Executor, ExecutorService, and ScheduledExecutorService
    Customization of Executors
    15.10. Messaging
    15.10.1. Spring Integration and Spring Cloud Stream
    15.10.2. Spring RabbitMq
    15.10.3. Spring Kafka
    15.10.4. Spring JMS
    15.11. Zuul
    16. Running examples

    2.1.3.BUILD-SNAPSHOT

    1. Introduction

    Spring Cloud Sleuth implements a distributed tracing solution for Spring Cloud.

    1.1 Terminology

    Spring Cloud Sleuth borrows Dapper’s terminology.

    Span: The basic unit of work. For example, sending an RPC is a new span, as is sending a response to an RPC. Spans are identified by a unique 64-bit ID for the span and another 64-bit ID for the trace the span is a part of. Spans also have other data, such as descriptions, timestamped events, key-value annotations (tags), the ID of the span that caused them, and process IDs (normally IP addresses).

    Spans can be started and stopped, and they keep track of their timing information. Once you create a span, you must stop it at some point in the future.

    [Tip]Tip

    The initial span that starts a trace is called a root span. The value of the ID @@ -53,7 +53,7 @@ An example from Kibana would resemble the following image:

    JSON Logback with Logstash

    Often, you do not want to store your logs in a text file but in a JSON file that Logstash can immediately pick. -To do so, you have to do the following (for readability, we pass the dependencies in the groupId:artifactId:version notation).

    Dependencies Setup

    1. Ensure that Logback is on the classpath (ch.qos.logback:logback-core).
    2. Add Logstash Logback encode. For example, to use version 4.6, add net.logstash.logback:logstash-logback-encoder:4.6.

    Logback Setup

    Consider the following example of a Logback configuration file (named logback-spring.xml).

    <?xml version="1.0" encoding="UTF-8"?>
    +To do so, you have to do the following (for readability, we pass the dependencies in the groupId:artifactId:version notation).

    Dependencies Setup

    1. Ensure that Logback is on the classpath (ch.qos.logback:logback-core).
    2. Add Logstash Logback encode. For example, to use version 4.6, add net.logstash.logback:logstash-logback-encoder:4.6.

    Logback Setup

    Consider the following example of a Logback configuration file (named logback-spring.xml).

    <?xml version="1.0" encoding="UTF-8"?>
     <configuration>
     	<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
     	​
    @@ -244,15 +244,15 @@ dependencies {
     

    1

    We recommend that you add the dependency management through the Spring BOM so that you need not manage versions yourself.

    2

    Add the dependency to spring-cloud-starter-zipkin. That way, all nested dependencies get downloaded.

    3

    To automatically configure RabbitMQ, add the spring-rabbit dependency.

    1.4 Overriding the auto-configuration of Zipkin

    Spring Cloud Sleuth supports sending traces to multiple tracing systems as of version 2.1.0. In order to get this to work, every tracing system needs to have a Reporter<Span> and Sender. If you want to override the provided beans you need to give them a specific name. -To do this you can use respectively ZipkinAutoConfiguration.REPORTER_BEAN_NAME and ZipkinAutoConfiguration.SENDER_BEAN_NAME.

    @Configuration
    +To do this you can use respectively ZipkinAutoConfiguration.REPORTER_BEAN_NAME and ZipkinAutoConfiguration.SENDER_BEAN_NAME.

    @Configuration
     protected static class MyConfig {
     
    -	@Bean(ZipkinAutoConfiguration.REPORTER_BEAN_NAME)
    +	@Bean(ZipkinAutoConfiguration.REPORTER_BEAN_NAME)
     	Reporter<zipkin2.Span> myReporter() {
     		return AsyncReporter.create(mySender());
     	}
     
    -	@Bean(ZipkinAutoConfiguration.SENDER_BEAN_NAME)
    +	@Bean(ZipkinAutoConfiguration.SENDER_BEAN_NAME)
     	MySender mySender() {
     		return new MySender();
     	}
    @@ -265,22 +265,22 @@ To do this you can use respectively ZipkinAutoConfiguratio
     			return this.spanSent;
     		}
     
    -		@Override
    +		@Override
     		public Encoding encoding() {
     			return Encoding.JSON;
     		}
     
    -		@Override
    +		@Override
     		public int messageMaxBytes() {
     			return Integer.MAX_VALUE;
     		}
     
    -		@Override
    +		@Override
     		public int messageSizeInBytes(List<byte[]> encodedSpans) {
     			return encoding().listSizeInBytes(encodedSpans);
     		}
     
    -		@Override
    +		@Override
     		public Call<Void> sendSpans(List<byte[]> encodedSpans) {
     			this.spanSent = true;
     			return Call.create(null);
    @@ -330,7 +330,7 @@ It also includes libraries to propagate the trace context over network boundarie
     Your names have to be explicit and concrete.
     Big names lead to latency issues and sometimes even thrown exceptions.

    The tracer creates and joins spans that model the latency of potentially distributed work. It can employ sampling to reduce overhead during the process, to reduce the amount of data sent to Zipkin, or both.

    Spans returned by a tracer report data to Zipkin when finished or do nothing if unsampled. -After starting a span, you can annotate events of interest or add tags containing details or lookup keys.

    Spans have a context that includes trace identifiers that place the span at the correct spot in the tree representing the distributed operation.

    3.1.2 Local Tracing

    When tracing code that never leaves your process, run it inside a scoped span.

    @Autowired Tracer tracer;
    +After starting a span, you can annotate events of interest or add tags containing details or lookup keys.

    Spans have a context that includes trace identifiers that place the span at the correct spot in the tree representing the distributed operation.

    3.1.2 Local Tracing

    When tracing code that never leaves your process, run it inside a scoped span.

    @Autowired Tracer tracer;
     
     // Start a new trace or a span within an existing trace representing an operation
     ScopedSpan span = tracer.startScopedSpan("encode");
    @@ -342,7 +342,7 @@ ScopedSpan span = tracer.startScopedSpan(throw e;
     } finally {
       span.finish(); // always finish the span
    -}

    When you need more features, or finer control, use the Span type:

    @Autowired Tracer tracer;
    +}

    When you need more features, or finer control, use the Span type:

    @Autowired Tracer tracer;
     
     // Start a new trace or a span within an existing trace representing an operation
     Span span = tracer.nextSpan().name("encode").start();
    @@ -364,19 +364,19 @@ The former is simpler to understand and test and does not tempt users with span
       callback.request(request, span);
     }

    3.1.4 Implicitly Looking up the Current Span

    Sometimes, you do not know if a trace is in progress or not, and you do not want users to do null checks. brave.CurrentSpanCustomizer handles this problem by adding data to any span that’s in progress or drops, as shown in the following example:

    Ex.

    // The user code can then inject this without a chance of it being null.
    -@Autowired SpanCustomizer span;
    +@Autowired SpanCustomizer span;
     
     void userCode() {
       span.annotate("tx.started");
       ...
    -}

    3.1.5 RPC tracing

    [Tip]Tip

    Check for instrumentation written here and Zipkin’s list before rolling your own RPC instrumentation.

    RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation.

    The following example shows how to add a client span:

    @Autowired Tracing tracing;
    -@Autowired Tracer tracer;
    +}

    3.1.5 RPC tracing

    [Tip]Tip

    Check for instrumentation written here and Zipkin’s list before rolling your own RPC instrumentation.

    RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation.

    The following example shows how to add a client span:

    @Autowired Tracing tracing;
    +@Autowired Tracer tracer;
     
     // before you send a request, add metadata that describes the operation
     span = tracer.nextSpan().name(service + "/" + method).kind(CLIENT);
     span.tag("myrpc.version", "1.0.0");
     span.remoteServiceName("backend");
    -span.remoteIpAndPort("172.3.4.1", 8108);
    +span.remoteIpAndPort("172.3.4.1", 8108);
     
     // Add the trace context to the request, so it can be propagated in-band
     tracing.propagation().injector(Request::addHeader)
    @@ -394,8 +394,8 @@ span.error(exception);
     span.finish();

    One-Way tracing

    Sometimes, you need to model an asynchronous operation where there is a request but no response. In normal RPC tracing, you use span.finish() to indicate that the response was received. In one-way tracing, you use -span.flush() instead, as you do not expect a response.

    The following example shows how a client might model a one-way operation:

    @Autowired Tracing tracing;
    -@Autowired Tracer tracer;
    +span.flush() instead, as you do not expect a response.

    The following example shows how a client might model a one-way operation:

    @Autowired Tracing tracing;
    +@Autowired Tracer tracer;
     
     // start a new span representing a client request
     oneWaySend = tracer.nextSpan().name(service + "/" + method).kind(CLIENT);
    @@ -408,8 +408,8 @@ tracing.propagation().injector(Request::addHeader)
     request.execute();
     
     // start the client side and flush instead of finish
    -oneWaySend.start().flush();

    The following example shows how a server might handle a one-way operation:

    @Autowired Tracing tracing;
    -@Autowired Tracer tracer;
    +oneWaySend.start().flush();

    The following example shows how a server might handle a one-way operation:

    @Autowired Tracing tracing;
    +@Autowired Tracer tracer;
     
     // pull the context out of the incoming request
     extractor = tracing.propagation().extractor(Request::getHeader);
    @@ -428,12 +428,12 @@ oneWayReceive.start().flush();
     next = tracer.newSpan(oneWayReceive.context()).name("step2").start();

    4. Sampling

    Sampling may be employed to reduce the data collected and reported out of process. When a span is not sampled, it adds no overhead (a noop).

    Sampling is an up-front decision, meaning that the decision to report data is made at the first operation in a trace and that decision is propagated downstream.

    By default, a global sampler applies a single rate to all traced operations. Tracer.Builder.sampler controls this setting, and it defaults to tracing every request.

    4.1 Declarative sampling

    Some applications need to sample based on the type or annotations of a java method.

    Most users use a framework interceptor to automate this sort of policy. -The following example shows how that might work internally:

    @Autowired Tracer tracer;
    +The following example shows how that might work internally:

    @Autowired Tracer tracer;
     
     // derives a sample rate from an annotation on a java method
     DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sampleRate);
     
    -@Around("@annotation(traced)")
    +@Around("@annotation(traced)")
     public Object traceThing(ProceedingJoinPoint pjp, Traced traced) throws Throwable {
       // When there is no trace in progress, this decides using an annotation
       Sampler decideUsingAnnotation = declarativeSampler.toSampler(traced);
    @@ -451,12 +451,12 @@ DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sam
       }
     }

    4.2 Custom sampling

    Depending on what the operation is, you may want to apply different policies. For example, you might not want to trace requests to static resources such as images, or you might want to trace all requests to a new api.

    Most users use a framework interceptor to automate this sort of policy. -The following example shows how that might work internally:

    @Autowired Tracer tracer;
    -@Autowired Sampler fallback;
    +The following example shows how that might work internally:

    @Autowired Tracer tracer;
    +@Autowired Sampler fallback;
     
     Span nextSpan(final Request input) {
       Sampler requestBased = Sampler() {
    -    @Override public boolean isSampled(long traceId) {
    +    @Override public boolean isSampled(long traceId) {
           if (input.url().startsWith("/experimental")) {
             return true;
           } else if (input.url().startsWith("/static")) {
    @@ -471,7 +471,7 @@ That means that traces appear in logs but not in any remote store.
     For testing the default is often enough, and it probably is all you need if you use only the logs (for example, with an ELK aggregator).
     If you export span data to Zipkin, there is also an Sampler.ALWAYS_SAMPLE setting that exports everything and a ProbabilityBasedSampler setting that samples a fixed fraction of spans.

    [Note]Note

    The ProbabilityBasedSampler is the default if you use spring-cloud-sleuth-zipkin. You can configure the exports by setting spring.sleuth.sampler.probability. -The passed value needs to be a double from 0.0 to 1.0.

    A sampler can be installed by creating a bean definition, as shown in the following example:

    @Bean
    +The passed value needs to be a double from 0.0 to 1.0.

    A sampler can be installed by creating a bean definition, as shown in the following example:

    @Bean
     public Sampler defaultSampler() {
     	return Sampler.ALWAYS_SAMPLE;
     }
    [Tip]Tip

    You can set the HTTP header X-B3-Flags to 1, or, when doing messaging, you can set the spanFlags header to 1. @@ -491,14 +491,14 @@ The most common propagation approach is to copy a trace context from a client by │ └──────────────┘ │ └───────────────────┘ │ └──────────────┘ │ │ │ │ │ └──────────────────┘ └──────────────────┘

    The names above are from B3 Propagation, which is built-in to Brave and has implementations in many languages and frameworks.

    Most users use a framework interceptor to automate propagation. -The next two examples show how that might work for a client and a server.

    The following example shows how client-side propagation might work:

    @Autowired Tracing tracing;
    +The next two examples show how that might work for a client and a server.

    The following example shows how client-side propagation might work:

    @Autowired Tracing tracing;
     
     // configure a function that injects a trace context into a request
     injector = tracing.propagation().injector(Request.Builder::addHeader);
     
     // before a request is sent, add the current span's context to it
    -injector.inject(span.context(), request);

    The following example shows how server-side propagation might work:

    @Autowired Tracing tracing;
    -@Autowired Tracer tracer;
    +injector.inject(span.context(), request);

    The following example shows how server-side propagation might work:

    @Autowired Tracing tracing;
    +@Autowired Tracer tracer;
     
     // configure a function that extracts the trace context from a request
     extractor = tracing.propagation().extractor(Request::getHeader);
    @@ -578,13 +578,13 @@ You can use Tracer.currentSpan() to add custom tags
     tracer.currentSpan().context(). To get the current trace id as String
     you can use the traceIdString() method like this: tracer.currentSpan().context().traceIdString().

    7.1 Setting a span in scope manually

    When writing new instrumentation, it is important to place a span you created in scope as the current span. Not only does doing so let users access it with Tracer.currentSpan(), but it also allows customizations such as SLF4J MDC to see the current trace IDs.

    Tracer.withSpanInScope(Span) facilitates this and is most conveniently employed by using the try-with-resources idiom. -Whenever external code might be invoked (such as proceeding an interceptor or otherwise), place the span in scope, as shown in the following example:

    @Autowired Tracer tracer;
    +Whenever external code might be invoked (such as proceeding an interceptor or otherwise), place the span in scope, as shown in the following example:

    @Autowired Tracer tracer;
     
     try (SpanInScope ws = tracer.withSpanInScope(span)) {
       return inboundRequest.invoke();
     } finally { // note the scope is independent of the span
       span.finish();
    -}

    In edge cases, you may need to clear the current span temporarily (for example, launching a task that should not be associated with the current request). To do tso, pass null to withSpanInScope, as shown in the following example:

    @Autowired Tracer tracer;
    +}

    In edge cases, you may need to clear the current span temporarily (for example, launching a task that should not be associated with the current request). To do tso, pass null to withSpanInScope, as shown in the following example:

    @Autowired Tracer tracer;
     
     try (SpanInScope cleared = tracer.withSpanInScope(null)) {
       startBackgroundThread();
    @@ -651,10 +651,10 @@ Span newSpan = null;
     		newSpan.finish();
     	}
     }
    [Important]Important

    After creating such a span, you must finish it. Otherwise it is not reported (for example, to Zipkin).

    10. Naming spans

    Picking a span name is not a trivial task. A span name should depict an operation name. -The name should be low cardinality, so it should not include identifiers.

    Since there is a lot of instrumentation going on, some span names are artificial:

    • controller-method-name when received by a Controller with a method name of controllerMethodName
    • async for asynchronous operations done with wrapped Callable and Runnable interfaces.
    • Methods annotated with @Scheduled return the simple name of the class.

    Fortunately, for asynchronous processing, you can provide explicit naming.

    10.1 @SpanName Annotation

    You can name the span explicitly by using the @SpanName annotation, as shown in the following example:

    	@SpanName("calculateTax")
    +The name should be low cardinality, so it should not include identifiers.

    Since there is a lot of instrumentation going on, some span names are artificial:

    • controller-method-name when received by a Controller with a method name of controllerMethodName
    • async for asynchronous operations done with wrapped Callable and Runnable interfaces.
    • Methods annotated with @Scheduled return the simple name of the class.

    Fortunately, for asynchronous processing, you can provide explicit naming.

    10.1 @SpanName Annotation

    You can name the span explicitly by using the @SpanName annotation, as shown in the following example:

    	@SpanName("calculateTax")
     	class TaxCountingRunnable implements Runnable {
     
    -		@Override
    +		@Override
     		public void run() {
     			// perform logic
     		}
    @@ -669,12 +669,12 @@ future.get();
    < Typically, one creates an anonymous instance of those classes. You cannot annotate such classes. To overcome that limitation, if there is no @SpanName annotation present, we check whether the class has a custom implementation of the toString() method.

    Running such code leads to creating a span named calculateTax, as shown in the following example:

    Runnable runnable = new TraceRunnable(this.tracing, spanNamer, new Runnable() {
    -	@Override
    +	@Override
     	public void run() {
     		// perform logic
     	}
     
    -	@Override
    +	@Override
     	public String toString() {
     		return "calculateTax";
     	}
    @@ -686,23 +686,23 @@ Doing so lets Sleuth change its core API to create less impact to user code.
  • Collaboration with runtime generated code. With libraries such as Spring Data and Feign, the implementations of interfaces are generated at runtime. Consequently, span wrapping of objects was tedious. Now you can provide annotations over interfaces and the arguments of those interfaces.
  • 11.2 Creating New Spans

    If you do not want to create local spans manually, you can use the @NewSpan annotation. -Also, we provide the @SpanTag annotation to add tags in an automated fashion.

    Now we can consider some examples of usage.

    @NewSpan
    -void testMethod();

    Annotating the method without any parameter leads to creating a new span whose name equals the annotated method name.

    @NewSpan("customNameOnTestMethod4")
    +Also, we provide the @SpanTag annotation to add tags in an automated fashion.

    Now we can consider some examples of usage.

    @NewSpan
    +void testMethod();

    Annotating the method without any parameter leads to creating a new span whose name equals the annotated method name.

    @NewSpan("customNameOnTestMethod4")
     void testMethod4();

    If you provide the value in the annotation (either directly or by setting the name parameter), the created span has the provided value as the name.

    // method declaration
    -@NewSpan(name = "customNameOnTestMethod5")
    -void testMethod5(@SpanTag("testTag") String param);
    +@NewSpan(name = "customNameOnTestMethod5")
    +void testMethod5(@SpanTag("testTag") String param);
     
     // and method execution
     this.testBean.testMethod5("test");

    You can combine both the name and a tag. Let’s focus on the latter. In this case, the value of the annotated method’s parameter runtime value becomes the value of the tag. -In our sample, the tag key is testTag, and the tag value is test.

    @NewSpan(name = "customNameOnTestMethod3")
    -@Override
    +In our sample, the tag key is testTag, and the tag value is test.

    @NewSpan(name = "customNameOnTestMethod3")
    +@Override
     public void testMethod3() {
     }

    You can place the @NewSpan annotation on both the class and an interface. If you override the interface’s method and provide a different value for the @NewSpan annotation, the most concrete one wins (in this case customNameOnTestMethod3 is set).

    11.3 Continuing Spans

    If you want to add tags and annotations to an existing span, you can use the @ContinueSpan annotation, as shown in the following example:

    // method declaration
    -@ContinueSpan(log = "testMethod11")
    -void testMethod11(@SpanTag("testTag11") String param);
    +@ContinueSpan(log = "testMethod11")
    +void testMethod11(@SpanTag("testTag11") String param);
     
     // method execution
     this.testBean.testMethod11("test");
    @@ -711,18 +711,18 @@ The precedence is as follows:

    11.4.1 Custom extractor

    The value of the tag for the following method is computed by an implementation of TagValueResolver interface. -Its class name has to be passed as the value of the resolver attribute.

    Consider the following annotated method:

    @NewSpan
    +Its class name has to be passed as the value of the resolver attribute.

    Consider the following annotated method:

    @NewSpan
     public void getAnnotationForTagValueResolver(
    -		@SpanTag(key = "test", resolver = TagValueResolver.class) String test) {
    -}

    Now further consider the following TagValueResolver bean implementation:

    @Bean(name = "myCustomTagValueResolver")
    +		@SpanTag(key = "test", resolver = TagValueResolver.class) String test) {
    +}

    Now further consider the following TagValueResolver bean implementation:

    @Bean(name = "myCustomTagValueResolver")
     public TagValueResolver tagValueResolver() {
     	return parameter -> "Value from myCustomTagValueResolver";
    -}

    The two preceding examples lead to setting a tag value equal to Value from myCustomTagValueResolver.

    11.4.2 Resolving Expressions for a Value

    Consider the following annotated method:

    @NewSpan
    +}

    The two preceding examples lead to setting a tag value equal to Value from myCustomTagValueResolver.

    11.4.2 Resolving Expressions for a Value

    Consider the following annotated method:

    @NewSpan
     public void getAnnotationForTagValueExpression(
    -		@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) {
    +		@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) {
     }

    No custom implementation of a TagValueExpressionResolver leads to evaluation of the SPEL expression, and a tag with a value of 4 characters is set on the span. -If you want to use some other expression resolution mechanism, you can create your own implementation of the bean.

    11.4.3 Using the toString() method

    Consider the following annotated method:

    @NewSpan
    -public void getAnnotationForArgumentToString(@SpanTag("test") Long param) {
    +If you want to use some other expression resolution mechanism, you can create your own implementation of the bean.

    11.4.3 Using the toString() method

    Consider the following annotated method:

    @NewSpan
    +public void getAnnotationForArgumentToString(@SpanTag("test") Long param) {
     }

    Running the preceding method with a value of 15 leads to setting a tag with a String value of "15".

    12. Customizations

    12.1 HTTP

    If a customization of client / server parsing of the HTTP related spans is required, just register a bean of type brave.http.HttpClientParser or brave.http.HttpServerParser. If client /server sampling is required, just @@ -733,14 +733,14 @@ register a bean of type brave.http.HttpSampler and reference the bean names via their static String NAME fields.

    Check out Brave’s code to see an example of how to make a path-based sampler https://github.com/openzipkin/brave/tree/master/instrumentation/http#sampling-policy

    If you want to completely rewrite the HttpTracing bean you can use the SkipPatternProvider interface to retrieve the URL Pattern for spans that should be not sampled. Below you can see -an example of usage of SkipPatternProvider inside a server side, HttpSampler.

    @Configuration
    +an example of usage of SkipPatternProvider inside a server side, HttpSampler.

    @Configuration
     class Config {
    -  @Bean(name = ServerSampler.NAME)
    +  @Bean(name = ServerSampler.NAME)
       HttpSampler myHttpSampler(SkipPatternProvider provider) {
       	Pattern pattern = provider.skipPattern();
       	return new HttpSampler() {
     
    -  		@Override
    +  		@Override
       		public <Req> Boolean trySample(HttpAdapter<Req, ?> adapter, Req request) {
       			String url = adapter.path(request);
       			boolean shouldSkip = pattern.matcher(url).matches();
    @@ -752,8 +752,8 @@ an example of usage of SkipPatternProvider inside a
       	};
       }
     }

    12.2 TracingFilter

    You can also modify the behavior of the TracingFilter, which is the component that is responsible for processing the input HTTP request and adding tags basing on the HTTP response. -You can customize the tags or modify the response headers by registering your own instance of the TracingFilter bean.

    In the following example, we register the TracingFilter bean, add the ZIPKIN-TRACE-ID response header containing the current Span’s trace id, and add a tag with key custom and a value tag to the span.

    @Component
    -@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1)
    +You can customize the tags or modify the response headers by registering your own instance of the TracingFilter bean.

    In the following example, we register the TracingFilter bean, add the ZIPKIN-TRACE-ID response header containing the current Span’s trace id, and add a tag with key custom and a value tag to the span.

    @Component
    +@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1)
     class MyFilter extends GenericFilterBean {
     
     	private final Tracer tracer;
    @@ -762,7 +762,7 @@ You can customize the tags or modify the response headers by registering your ow
     		this.tracer = tracer;
     	}
     
    -	@Override
    +	@Override
     	public void doFilter(ServletRequest request, ServletResponse response,
     			FilterChain chain) throws IOException, ServletException {
     		Span currentSpan = this.tracer.currentSpan();
    @@ -784,10 +784,10 @@ There are situations in which you want to explicitly provide a different service
     To achieve that, you can pass the following property to your application to override that value (the example is for a service named myService):

    spring.zipkin.service.name: myService

    12.4 Customization of Reported Spans

    Before reporting spans (for example, to Zipkin) you may want to modify that span in some way. You can do so by using the FinishedSpanHandler interface.

    In Sleuth, we generate spans with a fixed name. Some users want to modify the name depending on values of tags. -You can implement the FinishedSpanHandler interface to alter that name.

    The following example shows how to register two beans that implement FinishedSpanHandler:

    @Bean
    +You can implement the FinishedSpanHandler interface to alter that name.

    The following example shows how to register two beans that implement FinishedSpanHandler:

    @Bean
     FinishedSpanHandler handlerOne() {
     	return new FinishedSpanHandler() {
    -		@Override
    +		@Override
     		public boolean handle(TraceContext traceContext, MutableSpan span) {
     			span.name("foo");
     			return true; // keep this span
    @@ -795,10 +795,10 @@ FinishedSpanHandler handlerOne() {
     	};
     }
     
    -@Bean
    +@Bean
     FinishedSpanHandler handlerTwo() {
     	return new FinishedSpanHandler() {
    -		@Override
    +		@Override
     		public boolean handle(TraceContext traceContext, MutableSpan span) {
     			span.name(span.name() + " bar");
     			return true; // keep this span
    @@ -809,25 +809,25 @@ It is NOT about finding Zipkin thro
     The default approach is to take these values from server properties.
     If those are not set, we try to retrieve the host name from the network interfaces.

    If you have the discovery client enabled and prefer to retrieve the host address from the registered instance in a service registry, you have to set the spring.zipkin.locator.discovery.enabled property (it is applicable for both HTTP-based and Stream-based span reporting), as follows:

    spring.zipkin.locator.discovery.enabled: true

    13. Sending Spans to Zipkin

    By default, if you add spring-cloud-starter-zipkin as a dependency to your project, when the span is closed, it is sent to Zipkin over HTTP. The communication is asynchronous. -You can configure the URL by setting the spring.zipkin.baseUrl property, as follows:

    spring.zipkin.baseUrl: https://192.168.99.100:9411/

    If you want to find Zipkin through service discovery, you can pass the Zipkin’s service ID inside the URL, as shown in the following example for zipkinserver service ID:

    spring.zipkin.baseUrl: http://zipkinserver/

    To disable this feature just set spring.zipkin.discoveryClientEnabled to `false.

    When the Discovery Client feature is enabled, Sleuth uses +You can configure the URL by setting the spring.zipkin.baseUrl property, as follows:

    spring.zipkin.baseUrl: https://192.168.99.100:9411/

    If you want to find Zipkin through service discovery, you can pass the Zipkin’s service ID inside the URL, as shown in the following example for zipkinserver service ID:

    spring.zipkin.baseUrl: http://zipkinserver/

    To disable this feature just set spring.zipkin.discoveryClientEnabled to `false.

    When the Discovery Client feature is enabled, Sleuth uses LoadBalancerClient to find the URL of the Zipkin Server. It means that you can set up the load balancing configuration e.g. via Ribbon.

    zipkinserver:
       ribbon:
         ListOfServers: host1,host2

    If you have web, rabbit, or kafka together on the classpath, you might need to pick the means by which you would like to send spans to zipkin. To do so, set web, rabbit, or kafka to the spring.zipkin.sender.type property. The following example shows setting the sender type for web:

    spring.zipkin.sender.type: web

    To customize the RestTemplate that sends spans to Zipkin via HTTP, you can register -the ZipkinRestTemplateCustomizer bean.

    @Configuration
    +the ZipkinRestTemplateCustomizer bean.

    @Configuration
     class MyConfig {
    -	@Bean ZipkinRestTemplateCustomizer myCustomizer() {
    +	@Bean ZipkinRestTemplateCustomizer myCustomizer() {
     		return new ZipkinRestTemplateCustomizer() {
    -			@Override
    +			@Override
     			void customize(RestTemplate restTemplate) {
     				// customize the RestTemplate
     			}
     		};
     	}
     }

    If, however, you would like to control the full process of creating the RestTemplate -object, you will have to create a bean of zipkin2.reporter.Sender type.

    	@Bean Sender myRestTemplateSender(ZipkinProperties zipkin,
    +object, you will have to create a bean of zipkin2.reporter.Sender type.

    	@Bean Sender myRestTemplateSender(ZipkinProperties zipkin,
     			ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer) {
     		RestTemplate restTemplate = mySuperCustomRestTemplate();
     		zipkinRestTemplateCustomizer.customize(restTemplate);
    @@ -837,12 +837,12 @@ Starting from the Edgware release, the Zipkin Stream server is deprecated.
     In the Finchley release, it got removed.

    If for some reason you need to create the deprecated Stream Zipkin server, see the Dalston Documentation.

    15. Integrations

    15.1 OpenTracing

    Spring Cloud Sleuth is compatible with OpenTracing. If you have OpenTracing on the classpath, we automatically register the OpenTracing Tracer bean. If you wish to disable this, set spring.sleuth.opentracing.enabled to false

    15.2 Runnable and Callable

    If you wrap your logic in Runnable or Callable, you can wrap those classes in their Sleuth representative, as shown in the following example for Runnable:

    Runnable runnable = new Runnable() {
    -	@Override
    +	@Override
     	public void run() {
     		// do some work
     	}
     
    -	@Override
    +	@Override
     	public String toString() {
     		return "spanNameFromToStringMethod";
     	}
    @@ -854,12 +854,12 @@ Runnable traceRunnable = // in the thread of `Runnable`
     Runnable traceRunnableFromTracer = this.tracing.currentTraceContext()
     		.wrap(runnable);

    The following example shows how to do so for Callable:

    Callable<String> callable = new Callable<String>() {
    -	@Override
    +	@Override
     	public String call() throws Exception {
     		return someLogic();
     	}
     
    -	@Override
    +	@Override
     	public String toString() {
     		return "spanNameFromToStringMethod";
     	}
    @@ -873,13 +873,13 @@ Callable<String> traceCallableFromTracer = 

    15.3 Hystrix

    15.3.1 Custom Concurrency Strategy

    We register a custom HystrixConcurrencyStrategy called TraceCallable that wraps all Callable instances in their Sleuth representative. The strategy either starts or continues a span, depending on 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.

    15.3.2 Manual Command setting

    Assume that you have the following HystrixCommand:

    HystrixCommand<String> hystrixCommand = new HystrixCommand<String>(setter) {
    -	@Override
    +	@Override
     	protected String run() throws Exception {
     		return someLogic();
     	}
     };

    To pass the tracing information, you have to wrap the same logic in the Sleuth version of the HystrixCommand, which is called TraceCommand, as shown in the following example:

    TraceCommand<String> traceCommand = new TraceCommand<String>(tracer, setter) {
    -	@Override
    +	@Override
     	public String doRun() throws Exception {
     		return someLogic();
     	}
    @@ -922,11 +922,11 @@ Then we instrument it.

    To block the TraceAsyncClientHttpRequestFactoryWrapper, set spring.sleuth.web.async.client.factory.enabled to false. If you do not want to create AsyncRestClient at all, set spring.sleuth.web.async.client.template.enabled to false.

    Multiple Asynchronous Rest Templates

    Sometimes you need to use multiple implementations of the Asynchronous Rest Template. -In the following snippet, you can see an example of how to set up such a custom AsyncRestTemplate:

    @Configuration
    -@EnableAutoConfiguration
    +In the following snippet, you can see an example of how to set up such a custom AsyncRestTemplate:

    @Configuration
    +@EnableAutoConfiguration
     static class Config {
     
    -	@Bean(name = "customAsyncRestTemplate")
    +	@Bean(name = "customAsyncRestTemplate")
     	public AsyncRestTemplate traceAsyncRestTemplate() {
     		return new AsyncRestTemplate(asyncClientFactory(),
     				clientHttpRequestFactory());
    @@ -947,7 +947,7 @@ In the following snippet, you can see an example of how to set up such a custom
     }

    15.6.3 WebClient

    We inject a ExchangeFilterFunction implementation that creates a span and, through on-success and on-error callbacks, takes care of closing client-side spans.

    To block this feature, set spring.sleuth.web.client.enabled to false.

    [Important]Important

    You have to register WebClient as a bean so that the tracing instrumentation gets applied. If you create a WebClient instance with a new keyword, the instrumentation does NOT work.

    15.6.4 Traverson

    If you use the Traverson library, you can inject a RestTemplate as a bean into your Traverson object. Since RestTemplate is already intercepted, you get full support for tracing in your client. The following pseudo code -shows how to do that:

    @Autowired RestTemplate restTemplate;
    +shows 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);
    @@ -972,30 +972,30 @@ You can disable this behavior by setting the value of spri
     If you use spring-cloud-sleuth-stream and spring-cloud-netflix-hystrix-stream together, a span is created for each Hystrix metrics and sent to Zipkin.
     This behavior may be annoying. That’s why, by default, spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask.

    15.9.3 Executor, ExecutorService, and ScheduledExecutorService

    We provide LazyTraceExecutor, TraceableExecutorService, and TraceableScheduledExecutorService. Those implementations create spans each time a new task is submitted, invoked, or scheduled.

    The following example shows how to pass tracing information with TraceableExecutorService when working with CompletableFuture:

    CompletableFuture<Long> completableFuture = CompletableFuture.supplyAsync(() -> {
     	// perform some logic
    -	return 1_000_000L;
    +	return 1_000_000L;
     }, new TraceableExecutorService(beanFactory, executorService,
     		// 'calculateTax' explicitly names the span - this param is optional
     		"calculateTax"));
    [Important]Important

    Sleuth does not work with parallelStream() out of the box. If you want to have the tracing information propagated through the stream, you have to use the approach with supplyAsync(...), as shown earlier.

    If there are beans that implement the Executor interface that you would like to exclude from span creation, you can use the spring.sleuth.async.ignored-beans property where you can provide a list of bean names.

    Customization of Executors

    Sometimes, you need to set up a custom instance of the AsyncExecutor. -The following example shows how to set up such a custom Executor:

    @Configuration
    -@EnableAutoConfiguration
    -@EnableAsync
    +The following example shows how to set up such a custom Executor:

    @Configuration
    +@EnableAutoConfiguration
    +@EnableAsync
     // add the infrastructure role to ensure that the bean gets auto-proxied
    -@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    +@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
     static class CustomExecutorConfig extends AsyncConfigurerSupport {
     
    -	@Autowired
    +	@Autowired
     	BeanFactory beanFactory;
     
    -	@Override
    +	@Override
     	public Executor getAsyncExecutor() {
     		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
     		// CUSTOMIZE HERE
    -		executor.setCorePoolSize(7);
    -		executor.setMaxPoolSize(42);
    -		executor.setQueueCapacity(11);
    +		executor.setCorePoolSize(7);
    +		executor.setMaxPoolSize(42);
    +		executor.setQueueCapacity(11);
     		executor.setThreadNamePrefix("MyExecutor-");
     		// DON'T FORGET TO INITIALIZE
     		executor.initialize();
    diff --git a/2.1.x/spring-cloud-sleuth.xml b/2.1.x/spring-cloud-sleuth.xml
    index 4b00a8241..8e641d221 100644
    --- a/2.1.x/spring-cloud-sleuth.xml
    +++ b/2.1.x/spring-cloud-sleuth.xml
    @@ -4,7 +4,7 @@
     
     
     Spring Cloud Sleuth
    -2019-06-06
    +2019-06-28
     
     
     Adrian Cole, Spencer Gibb, Marcin Grzejszczak, Dave Syer, Jay Bryant
    @@ -14,7 +14,7 @@
     
     
     
    -2.1.2.BUILD-SNAPSHOT
    +2.1.3.BUILD-SNAPSHOT
     
     
     Introduction