diff --git a/multi/multi__customizations.html b/multi/multi__customizations.html
index 6c076f043..9018db978 100644
--- a/multi/multi__customizations.html
+++ b/multi/multi__customizations.html
@@ -17,7 +17,8 @@ an example of usage of SkipPatternProvider inside a
Pattern pattern = provider.skipPattern();
return new HttpSampler() {
- @Override public <Req> Boolean trySample(HttpAdapter<Req, ?> adapter, Req request) {
+ @Override
+ public <Req> Boolean trySample(HttpAdapter<Req, ?> adapter, Req request) {
String url = adapter.path(request);
boolean shouldSkip = pattern.matcher(url).matches();
if (shouldSkip) {
@@ -38,7 +39,8 @@ You can customize the tags or modify the response headers by registering your ow
this.tracer = tracer;
}
- @Override public void doFilter(ServletRequest request, ServletResponse response,
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
Span currentSpan = this.tracer.currentSpan();
if (currentSpan == null) {
@@ -46,32 +48,36 @@ You can customize the tags or modify the response headers by registering your ow
return;
}
// for readability we're returning trace id in a hex form
- ((HttpServletResponse) response)
- .addHeader("ZIPKIN-TRACE-ID",
- currentSpan.context().traceIdString());
+ ((HttpServletResponse) response).addHeader("ZIPKIN-TRACE-ID",
+ currentSpan.context().traceIdString());
// we can also add some custom tags
currentSpan.tag("custom", "tag");
chain.doFilter(request, response);
}
+
}
-//end::response_headers[]
By default, Sleuth assumes that, when you send a span to Zipkin, you want the span’s service name to be equal to the value of the spring.application.name property.
+// end::response_headers[]
By default, Sleuth assumes that, when you send a span to Zipkin, you want the span’s service name to be equal to the value of the spring.application.name property.
That is not always the case, though.
There are situations in which you want to explicitly provide a different service name for all spans coming from your application.
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: myServiceBefore 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 FinishedSpanHandler handlerOne() { +You can implement theFinishedSpanHandlerinterface to alter that name.The following example shows how to register two beans that implement
FinishedSpanHandler:@Bean +FinishedSpanHandler handlerOne() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name("foo"); return true; // keep this span } }; } -@Bean FinishedSpanHandler handlerTwo() { +@Bean +FinishedSpanHandler handlerTwo() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name(span.name() + " bar"); return true; // keep this span } diff --git a/multi/multi__integrations.html b/multi/multi__integrations.html index 03b3f2c12..285c4c2f5 100644 --- a/multi/multi__integrations.html +++ b/multi/multi__integrations.html @@ -34,7 +34,8 @@ Callable<String> traceCallable = "calculateTax"); // Wrapping `Callable` with `Tracing`. That way the current span will be available // in the thread of `Callable` -Callable<String> traceCallableFromTracer = tracing.currentTraceContext().wrap(callable);That way, you ensure that a new span is created and closed for each execution.
We register a custom HystrixConcurrencyStrategy called TraceCallable that wraps all Callable instances in their Sleuth representative.
+Callable<String> traceCallableFromTracer = tracing.currentTraceContext()
+ .wrap(callable);
That way, you ensure that a new span is created and closed for each execution.
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.
Assume that you have the following HystrixCommand:
HystrixCommand<String> hystrixCommand = new HystrixCommand<String>(setter) { @Override @@ -90,20 +91,22 @@ In the following snippet, you can see an example of how to set up such a custom @Bean(name = "customAsyncRestTemplate") public AsyncRestTemplate traceAsyncRestTemplate() { - return new AsyncRestTemplate(asyncClientFactory(), clientHttpRequestFactory()); + return new AsyncRestTemplate(asyncClientFactory(), + clientHttpRequestFactory()); } private ClientHttpRequestFactory clientHttpRequestFactory() { ClientHttpRequestFactory clientHttpRequestFactory = new CustomClientHttpRequestFactory(); - //CUSTOMIZE HERE + // CUSTOMIZE HERE return clientHttpRequestFactory; } private AsyncClientHttpRequestFactory asyncClientFactory() { AsyncClientHttpRequestFactory factory = new CustomAsyncClientHttpRequestFactory(); - //CUSTOMIZE HERE + // CUSTOMIZE HERE return factory; } + }
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 |
|---|---|
You have to register |
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
@@ -136,9 +139,11 @@ The following example shows how to set up such a custom Ex
@EnableAsync
static class CustomExecutorConfig extends AsyncConfigurerSupport {
- @Autowired BeanFactory beanFactory;
+ @Autowired
+ BeanFactory beanFactory;
- @Override public Executor getAsyncExecutor() {
+ @Override
+ public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// CUSTOMIZE HERE
executor.setCorePoolSize(7);
@@ -149,6 +154,7 @@ The following example shows how to set up such a custom Ex
executor.initialize();
return new LazyTraceExecutor(this.beanFactory, executor);
}
+
}
Features from this section can be disabled by setting the spring.sleuth.messaging.enabled property with value equal to false.
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.
diff --git a/multi/multi__introduction.html b/multi/multi__introduction.html
index a06d05a27..3ea4a9260 100644
--- a/multi/multi__introduction.html
+++ b/multi/multi__introduction.html
@@ -137,7 +137,7 @@ Spring Cloud Sleuth understands that a header is baggage-related if the HTTP hea
However, keep in mind that too many can decrease system throughput or increase RPC latency.
In extreme cases, too much baggage can crash the application, due to exceeding transport-level message or header capacity.
The following example shows setting baggage on a span:
Span initialSpan = this.tracer.nextSpan().name("span").start(); ExtraFieldPropagation.set(initialSpan.context(), "foo", "bar"); -ExtraFieldPropagation.set(initialSpan.context(),"UPPER_CASE", "someValue"); +ExtraFieldPropagation.set(initialSpan.context(), "UPPER_CASE", "someValue"); }
Baggage travels with the trace (every child span contains the baggage of its parent). Zipkin has no knowledge of baggage and does not receive that information.
![]() | Important |
|---|---|
Starting from Sleuth 2.0.0 you have to pass the baggage key names explicitly in your project configuration. Read more about that setup here |
Tags are attached to a specific span. In other words, they are presented only for that particular span.
diff --git a/multi/multi__managing_spans_with_annotations.html b/multi/multi__managing_spans_with_annotations.html
index ffce8c7e5..cd81acde9 100644
--- a/multi/multi__managing_spans_with_annotations.html
+++ b/multi/multi__managing_spans_with_annotations.html
@@ -31,12 +31,14 @@ We search for a TagValueExpressionResolver bean.
The default implementation uses SPEL expression resolution.
IMPORTANT You can only reference properties from the SPEL expression. Method execution is not allowed due to security constraints.
toString() value of the parameter.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 -public void getAnnotationForTagValueResolver(@SpanTag(key = "test", resolver = TagValueResolver.class) String test) { +public void getAnnotationForTagValueResolver( + @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.
Consider the following annotated method:
@NewSpan -public void getAnnotationForTagValueExpression(@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) { +public void getAnnotationForTagValueExpression( + @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.
Consider the following annotated method:
@NewSpan public void getAnnotationForArgumentToString(@SpanTag("test") Long param) { diff --git a/multi/multi__naming_spans.html b/multi/multi__naming_spans.html index 7ba3a9dfd..de3accbe9 100644 --- a/multi/multi__naming_spans.html +++ b/multi/multi__naming_spans.html @@ -4,9 +4,11 @@ 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-namewhen received by a Controller with a method name ofcontrollerMethodNameasyncfor asynchronous operations done with wrappedCallableandRunnableinterfaces.- Methods annotated with
@Scheduledreturn the simple name of the class.Fortunately, for asynchronous processing, you can provide explicit naming.
You can name the span explicitly by using the
@SpanNameannotation, as shown in the following example:@SpanName("calculateTax") class TaxCountingRunnable implements Runnable { - @Override public void run() { + @Override + public void run() { // perform logic } + }In this case, when processed in the following manner, the span is named
calculateTax:Runnable runnable = new TraceRunnable(tracing, spanNamer, new TaxCountingRunnable()); Future<?> future = executorService.submit(runnable); @@ -15,11 +17,13 @@ future.get();< Typically, one creates an anonymous instance of those classes. You cannot annotate such classes. To overcome that limitation, if there is no@SpanNameannotation present, we check whether the class has a custom implementation of thetoString()method.Running such code leads to creating a span named
calculateTax, as shown in the following example:Runnable runnable = new TraceRunnable(tracing, spanNamer, new Runnable() { - @Override public void run() { + @Override + public void run() { // perform logic } - @Override public String toString() { + @Override + public String toString() { return "calculateTax"; } }); diff --git a/multi/multi__span_lifecycle.html b/multi/multi__span_lifecycle.html index 66dc72b91..2401e81e8 100644 --- a/multi/multi__span_lifecycle.html +++ b/multi/multi__span_lifecycle.html @@ -12,7 +12,8 @@ Span newSpan = // ... // You can log an event on a span newSpan.annotate("taxCalculated"); -} finally { +} +finally { // Once done remember to finish the span. This will allow collecting // the span to send it to Zipkin newSpan.finish(); @@ -30,7 +31,8 @@ Span continuedSpan = // ... // You can log an event on a span continuedSpan.annotate("taxCalculated"); -} finally { +} +finally { // Once done remember to flush the span. That means that // it will get reported but the span itself is not yet finished continuedSpan.flush(); @@ -49,7 +51,8 @@ Span newSpan = null; // ... // You can log an event on a span newSpan.annotate("commissionCalculated"); -} finally { +} +finally { // Once done remember to finish the span. This will allow collecting // the span to send it to Zipkin. The tags and events set on the // newSpan will not be present on the parent diff --git a/single/spring-cloud-sleuth.html b/single/spring-cloud-sleuth.html index f7eb90302..f2e2cde89 100644 --- a/single/spring-cloud-sleuth.html +++ b/single/spring-cloud-sleuth.html @@ -137,7 +137,7 @@ Spring Cloud Sleuth understands that a header is baggage-related if the HTTP hea However, keep in mind that too many can decrease system throughput or increase RPC latency. In extreme cases, too much baggage can crash the application, due to exceeding transport-level message or header capacity.The following example shows setting baggage on a span:
Span initialSpan = this.tracer.nextSpan().name("span").start(); ExtraFieldPropagation.set(initialSpan.context(), "foo", "bar"); -ExtraFieldPropagation.set(initialSpan.context(),"UPPER_CASE", "someValue"); +ExtraFieldPropagation.set(initialSpan.context(), "UPPER_CASE", "someValue"); }Baggage travels with the trace (every child span contains the baggage of its parent). Zipkin has no knowledge of baggage and does not receive that information.
Important Starting from Sleuth 2.0.0 you have to pass the baggage key names explicitly in your project configuration. Read more about that setup here
Tags are attached to a specific span. In other words, they are presented only for that particular span. @@ -557,7 +557,8 @@ Span newSpan = // ... // You can log an event on a span newSpan.annotate("taxCalculated"); -} finally { +} +finally { // Once done remember to finish the span. This will allow collecting // the span to send it to Zipkin newSpan.finish(); @@ -575,7 +576,8 @@ Span continuedSpan = // ... // You can log an event on a span continuedSpan.annotate("taxCalculated"); -} finally { +} +finally { // Once done remember to flush the span. That means that // it will get reported but the span itself is not yet finished continuedSpan.flush(); @@ -594,7 +596,8 @@ Span newSpan = null; // ... // You can log an event on a span newSpan.annotate("commissionCalculated"); -} finally { +} +finally { // Once done remember to finish the span. This will allow collecting // the span to send it to Zipkin. The tags and events set on the // newSpan will not be present on the parent @@ -605,9 +608,11 @@ Span newSpan = null; 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-namewhen received by a Controller with a method name ofcontrollerMethodNameasyncfor asynchronous operations done with wrappedCallableandRunnableinterfaces.- Methods annotated with
@Scheduledreturn the simple name of the class.Fortunately, for asynchronous processing, you can provide explicit naming.
You can name the span explicitly by using the
@SpanNameannotation, as shown in the following example:@SpanName("calculateTax") class TaxCountingRunnable implements Runnable { - @Override public void run() { + @Override + public void run() { // perform logic } + }In this case, when processed in the following manner, the span is named
calculateTax:Runnable runnable = new TraceRunnable(tracing, spanNamer, new TaxCountingRunnable()); Future<?> future = executorService.submit(runnable); @@ -616,11 +621,13 @@ future.get();< Typically, one creates an anonymous instance of those classes. You cannot annotate such classes. To overcome that limitation, if there is no@SpanNameannotation present, we check whether the class has a custom implementation of thetoString()method.Running such code leads to creating a span named
calculateTax, as shown in the following example:Runnable runnable = new TraceRunnable(tracing, spanNamer, new Runnable() { - @Override public void run() { + @Override + public void run() { // perform logic } - @Override public String toString() { + @Override + public String toString() { return "calculateTax"; } }); @@ -657,12 +664,14 @@ We search for aTagValueExpressionResolverbean. The default implementation uses SPEL expression resolution. IMPORTANT You can only reference properties from the SPEL expression. Method execution is not allowed due to security constraints.If we do not find any expression to evaluate, return the toString()value of the parameter.The value of the tag for the following method is computed by an implementation of
TagValueResolverinterface. Its class name has to be passed as the value of theresolverattribute.Consider the following annotated method:
@NewSpan -public void getAnnotationForTagValueResolver(@SpanTag(key = "test", resolver = TagValueResolver.class) String test) { +public void getAnnotationForTagValueResolver( + @SpanTag(key = "test", resolver = TagValueResolver.class) String test) { }Now further consider the following
TagValueResolverbean 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.Consider the following annotated method:
@NewSpan -public void getAnnotationForTagValueExpression(@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) { +public void getAnnotationForTagValueExpression( + @SpanTag(key = "test", expression = "'hello' + ' characters'") String test) { }No custom implementation of a
TagValueExpressionResolverleads to evaluation of the SPEL expression, and a tag with a value of4 charactersis set on the span. If you want to use some other expression resolution mechanism, you can create your own implementation of the bean.Consider the following annotated method:
@NewSpan public void getAnnotationForArgumentToString(@SpanTag("test") Long param) { @@ -683,7 +692,8 @@ an example of usage ofSkipPatternProviderinside a Pattern pattern = provider.skipPattern(); return new HttpSampler() { - @Override public <Req> Boolean trySample(HttpAdapter<Req, ?> adapter, Req request) { + @Override + public <Req> Boolean trySample(HttpAdapter<Req, ?> adapter, Req request) { String url = adapter.path(request); boolean shouldSkip = pattern.matcher(url).matches(); if (shouldSkip) { @@ -704,7 +714,8 @@ You can customize the tags or modify the response headers by registering your ow this.tracer = tracer; } - @Override public void doFilter(ServletRequest request, ServletResponse response, + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Span currentSpan = this.tracer.currentSpan(); if (currentSpan == null) { @@ -712,32 +723,36 @@ You can customize the tags or modify the response headers by registering your ow return; } // for readability we're returning trace id in a hex form - ((HttpServletResponse) response) - .addHeader("ZIPKIN-TRACE-ID", - currentSpan.context().traceIdString()); + ((HttpServletResponse) response).addHeader("ZIPKIN-TRACE-ID", + currentSpan.context().traceIdString()); // we can also add some custom tags currentSpan.tag("custom", "tag"); chain.doFilter(request, response); } + } -//end::response_headers[]By default, Sleuth assumes that, when you send a span to Zipkin, you want the span’s service name to be equal to the value of the
spring.application.nameproperty. +// end::response_headers[]By default, Sleuth assumes that, when you send a span to Zipkin, you want the span’s service name to be equal to the value of the
spring.application.nameproperty. That is not always the case, though. There are situations in which you want to explicitly provide a different service name for all spans coming from your application. To achieve that, you can pass the following property to your application to override that value (the example is for a service namedmyService):spring.zipkin.service.name: myServiceBefore reporting spans (for example, to Zipkin) you may want to modify that span in some way. You can do so by using the
FinishedSpanHandlerinterface.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
FinishedSpanHandlerinterface to alter that name.The following example shows how to register two beans that implement
FinishedSpanHandler:@Bean FinishedSpanHandler handlerOne() { +You can implement theFinishedSpanHandlerinterface to alter that name.The following example shows how to register two beans that implement
FinishedSpanHandler:@Bean +FinishedSpanHandler handlerOne() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name("foo"); return true; // keep this span } }; } -@Bean FinishedSpanHandler handlerTwo() { +@Bean +FinishedSpanHandler handlerTwo() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name(span.name() + " bar"); return true; // keep this span } @@ -806,7 +821,8 @@ Callable<String> traceCallable = "calculateTax"); // Wrapping `Callable` with `Tracing`. That way the current span will be available // in the thread of `Callable` -Callable<String> traceCallableFromTracer = tracing.currentTraceContext().wrap(callable);That way, you ensure that a new span is created and closed for each execution.
We register a custom
HystrixConcurrencyStrategycalledTraceCallablethat wraps allCallableinstances in their Sleuth representative. +Callable<String> traceCallableFromTracer = tracing.currentTraceContext() + .wrap(callable);That way, you ensure that a new span is created and closed for each execution.
We register a custom
HystrixConcurrencyStrategycalledTraceCallablethat wraps allCallableinstances 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 thespring.sleuth.hystrix.strategy.enabledtofalse.Assume that you have the following
HystrixCommand:HystrixCommand<String> hystrixCommand = new HystrixCommand<String>(setter) { @Override @@ -862,20 +878,22 @@ In the following snippet, you can see an example of how to set up such a custom @Bean(name = "customAsyncRestTemplate") public AsyncRestTemplate traceAsyncRestTemplate() { - return new AsyncRestTemplate(asyncClientFactory(), clientHttpRequestFactory()); + return new AsyncRestTemplate(asyncClientFactory(), + clientHttpRequestFactory()); } private ClientHttpRequestFactory clientHttpRequestFactory() { ClientHttpRequestFactory clientHttpRequestFactory = new CustomClientHttpRequestFactory(); - //CUSTOMIZE HERE + // CUSTOMIZE HERE return clientHttpRequestFactory; } private AsyncClientHttpRequestFactory asyncClientFactory() { AsyncClientHttpRequestFactory factory = new CustomAsyncClientHttpRequestFactory(); - //CUSTOMIZE HERE + // CUSTOMIZE HERE return factory; } + }We inject a
ExchangeFilterFunctionimplementation 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.enabledtofalse.
Important You have to register
WebClientas a bean so that the tracing instrumentation gets applied. If you create aWebClientinstance with anewkeyword, the instrumentation does NOT work.If you use the Traverson library, you can inject a
RestTemplateas a bean into your Traverson object. SinceRestTemplateis already intercepted, you get full support for tracing in your client. The following pseudo code @@ -908,9 +926,11 @@ The following example shows how to set up such a customEx @EnableAsync static class CustomExecutorConfig extends AsyncConfigurerSupport { - @Autowired BeanFactory beanFactory; + @Autowired + BeanFactory beanFactory; - @Override public Executor getAsyncExecutor() { + @Override + public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // CUSTOMIZE HERE executor.setCorePoolSize(7); @@ -921,6 +941,7 @@ The following example shows how to set up such a customEx executor.initialize(); return new LazyTraceExecutor(this.beanFactory, executor); } + }Features from this section can be disabled by setting the
spring.sleuth.messaging.enabledproperty with value equal tofalse.Spring Cloud Sleuth integrates with Spring Integration. It creates spans for publish and subscribe events. To disable Spring Integration instrumentation, set
spring.sleuth.integration.enabledtofalse.You can provide the
spring.sleuth.integration.patternspattern to explicitly provide the names of channels that you want to include for tracing. diff --git a/spring-cloud-sleuth.xml b/spring-cloud-sleuth.xml index 593c38b0d..702df06e6 100644 --- a/spring-cloud-sleuth.xml +++ b/spring-cloud-sleuth.xml @@ -365,7 +365,7 @@ In extreme cases, too much baggage can crash the application, due to exceeding tThe following example shows setting baggage on a span: Span initialSpan = this.tracer.nextSpan().name("span").start(); ExtraFieldPropagation.set(initialSpan.context(), "foo", "bar"); -ExtraFieldPropagation.set(initialSpan.context(),"UPPER_CASE", "someValue"); +ExtraFieldPropagation.set(initialSpan.context(), "UPPER_CASE", "someValue"); } Baggage versus Span Tags @@ -1211,7 +1211,8 @@ try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(newSpan.start())) { // ... // You can log an event on a span newSpan.annotate("taxCalculated"); -} finally { +} +finally { // Once done remember to finish the span. This will allow collecting // the span to send it to Zipkin newSpan.finish(); @@ -1250,7 +1251,8 @@ try { // ... // You can log an event on a span continuedSpan.annotate("taxCalculated"); -} finally { +} +finally { // Once done remember to flush the span. That means that // it will get reported but the span itself is not yet finished continuedSpan.flush(); @@ -1274,7 +1276,8 @@ try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initialSpan)) { // ... // You can log an event on a span newSpan.annotate("commissionCalculated"); -} finally { +} +finally { // Once done remember to finish the span. This will allow collecting // the span to send it to Zipkin. The tags and events set on the // newSpan will not be present on the parent @@ -1310,9 +1313,11 @@ The name should be low cardinality, so it should not include identifiers.@SpanName("calculateTax") class TaxCountingRunnable implements Runnable { - @Override public void run() { + @Override + public void run() { // perform logic } + }In this case, when processed in the following manner, the span is named calculateTax :Runnable runnable = new TraceRunnable(tracing, spanNamer, @@ -1329,11 +1334,13 @@ 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 thetoString() method.Running such code leads to creating a span named calculateTax , as shown in the following example:Runnable runnable = new TraceRunnable(tracing, spanNamer, new Runnable() { - @Override public void run() { + @Override + public void run() { // perform logic } - @Override public String toString() { + @Override + public String toString() { return "calculateTax"; } }); @@ -1440,7 +1447,8 @@ The default implementation uses SPEL expression resolution. 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) { +public void getAnnotationForTagValueResolver( + @SpanTag(key = "test", resolver = TagValueResolver.class) String test) { } Now further consider the following TagValueResolver bean implementation:@Bean(name = "myCustomTagValueResolver") @@ -1453,7 +1461,8 @@ public TagValueResolver tagValueResolver() { +// end::response_headers[]Resolving Expressions for a Value Consider the following annotated method: @NewSpan -public void getAnnotationForTagValueExpression(@SpanTag(key = "test", expression = "'hello' + ' characters'") String test) { +public void getAnnotationForTagValueExpression( + @SpanTag(key = "test", expression = "'hello' + ' characters'") String test) { } No custom implementation of a @@ -1492,7 +1501,8 @@ class Config { Pattern pattern = provider.skipPattern(); return new HttpSampler() { - @Override public <Req> Boolean trySample(HttpAdapter<Req, ?> adapter, Req request) { + @Override + public <Req> Boolean trySample(HttpAdapter<Req, ?> adapter, Req request) { String url = adapter.path(request); boolean shouldSkip = pattern.matcher(url).matches(); if (shouldSkip) { @@ -1519,7 +1529,8 @@ class MyFilter extends GenericFilterBean { this.tracer = tracer; } - @Override public void doFilter(ServletRequest request, ServletResponse response, + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Span currentSpan = this.tracer.currentSpan(); if (currentSpan == null) { @@ -1527,15 +1538,15 @@ class MyFilter extends GenericFilterBean { return; } // for readability we're returning trace id in a hex form - ((HttpServletResponse) response) - .addHeader("ZIPKIN-TRACE-ID", - currentSpan.context().traceIdString()); + ((HttpServletResponse) response).addHeader("ZIPKIN-TRACE-ID", + currentSpan.context().traceIdString()); // we can also add some custom tags currentSpan.tag("custom", "tag"); chain.doFilter(request, response); } + } -//end::response_headers[]TagValueExpressionResolver leads to evaluation of the SPEL expression, and a tag with a value of4 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.Custom service name @@ -1553,18 +1564,22 @@ You can do so by using theFinishedSpanHandler interface.FinishedSpanHandler interface to alter that name.The following example shows how to register two beans that implement -FinishedSpanHandler :@Bean FinishedSpanHandler handlerOne() { + @Bean +FinishedSpanHandler handlerOne() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name("foo"); return true; // keep this span } }; } -@Bean FinishedSpanHandler handlerTwo() { +@Bean +FinishedSpanHandler handlerTwo() { return new FinishedSpanHandler() { - @Override public boolean handle(TraceContext traceContext, MutableSpan span) { + @Override + public boolean handle(TraceContext traceContext, MutableSpan span) { span.name(span.name() + " bar"); return true; // keep this span } @@ -1680,7 +1695,8 @@ Callable<String> traceCallable = new TraceCallable<>(tracing, spanNa "calculateTax"); // Wrapping `Callable` with `Tracing`. That way the current span will be available // in the thread of `Callable` -Callable<String> traceCallableFromTracer = tracing.currentTraceContext().wrap(callable); +Callable<String> traceCallableFromTracer = tracing.currentTraceContext() + .wrap(callable);That way, you ensure that a new span is created and closed for each execution. @@ -1810,20 +1826,22 @@ static class Config { @Bean(name = "customAsyncRestTemplate") public AsyncRestTemplate traceAsyncRestTemplate() { - return new AsyncRestTemplate(asyncClientFactory(), clientHttpRequestFactory()); + return new AsyncRestTemplate(asyncClientFactory(), + clientHttpRequestFactory()); } private ClientHttpRequestFactory clientHttpRequestFactory() { ClientHttpRequestFactory clientHttpRequestFactory = new CustomClientHttpRequestFactory(); - //CUSTOMIZE HERE + // CUSTOMIZE HERE return clientHttpRequestFactory; } private AsyncClientHttpRequestFactory asyncClientFactory() { AsyncClientHttpRequestFactory factory = new CustomAsyncClientHttpRequestFactory(); - //CUSTOMIZE HERE + // CUSTOMIZE HERE return factory; } + } @@ -1940,9 +1958,11 @@ The following example shows how to set up such a customExecutor