183 lines
45 KiB
HTML
183 lines
45 KiB
HTML
<html><head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
|
<title>15. Integrations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="multi_spring-cloud-sleuth.html" title="Spring Cloud Sleuth"><link rel="up" href="multi_spring-cloud-sleuth.html" title="Spring Cloud Sleuth"><link rel="prev" href="multi__zipkin_stream_span_consumer.html" title="14. Zipkin Stream Span Consumer"><link rel="next" href="multi__running_examples.html" title="16. Running examples"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">15. Integrations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__zipkin_stream_span_consumer.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__running_examples.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_integrations" href="#_integrations"></a>15. Integrations</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_opentracing" href="#_opentracing"></a>15.1 OpenTracing</h2></div></div></div><p>Spring Cloud Sleuth is compatible with <a class="link" href="https://opentracing.io/" target="_top">OpenTracing</a>.
|
|
If you have OpenTracing on the classpath, we automatically register the OpenTracing <code class="literal">Tracer</code> bean.
|
|
If you wish to disable this, set <code class="literal">spring.sleuth.opentracing.enabled</code> to <code class="literal">false</code></p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_runnable_and_callable" href="#_runnable_and_callable"></a>15.2 Runnable and Callable</h2></div></div></div><p>If you wrap your logic in <code class="literal">Runnable</code> or <code class="literal">Callable</code>, you can wrap those classes in their Sleuth representative, as shown in the following example for <code class="literal">Runnable</code>:</p><pre class="programlisting">Runnable runnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Runnable() {
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> run() {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// do some work</span>
|
|
}
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String toString() {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spanNameFromToStringMethod"</span>;
|
|
}
|
|
};
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Manual `TraceRunnable` creation with explicit "calculateTax" Span name</span>
|
|
Runnable traceRunnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceRunnable(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracing, spanNamer, runnable,
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateTax"</span>);
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Wrapping `Runnable` with `Tracing`. That way the current span will be available</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// in the thread of `Runnable`</span>
|
|
Runnable traceRunnableFromTracer = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracing.currentTraceContext()
|
|
.wrap(runnable);</pre><p>The following example shows how to do so for <code class="literal">Callable</code>:</p><pre class="programlisting">Callable<String> callable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Callable<String>() {
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String call() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> someLogic();
|
|
}
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String toString() {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"spanNameFromToStringMethod"</span>;
|
|
}
|
|
};
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Manual `TraceCallable` creation with explicit "calculateTax" Span name</span>
|
|
Callable<String> traceCallable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceCallable<>(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracing, spanNamer,
|
|
callable, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateTax"</span>);
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Wrapping `Callable` with `Tracing`. That way the current span will be available</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// in the thread of `Callable`</span>
|
|
Callable<String> traceCallableFromTracer = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracing.currentTraceContext()
|
|
.wrap(callable);</pre><p>That way, you ensure that a new span is created and closed for each execution.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_hystrix" href="#_hystrix"></a>15.3 Hystrix</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_custom_concurrency_strategy" href="#_custom_concurrency_strategy"></a>15.3.1 Custom Concurrency Strategy</h3></div></div></div><p>We register a custom <a class="link" href="https://github.com/Netflix/Hystrix/wiki/Plugins#concurrencystrategy" target="_top"><code class="literal">HystrixConcurrencyStrategy</code></a> called <code class="literal">TraceCallable</code> that wraps all <code class="literal">Callable</code> 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 <code class="literal">spring.sleuth.hystrix.strategy.enabled</code> to <code class="literal">false</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_manual_command_setting" href="#_manual_command_setting"></a>15.3.2 Manual Command setting</h3></div></div></div><p>Assume that you have the following <code class="literal">HystrixCommand</code>:</p><pre class="programlisting">HystrixCommand<String> hystrixCommand = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HystrixCommand<String>(setter) {
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> String run() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> someLogic();
|
|
}
|
|
};</pre><p>To pass the tracing information, you have to wrap the same logic in the Sleuth version of the <code class="literal">HystrixCommand</code>, which is called
|
|
<code class="literal">TraceCommand</code>, as shown in the following example:</p><pre class="programlisting">TraceCommand<String> traceCommand = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceCommand<String>(tracer, setter) {
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> String doRun() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Exception {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> someLogic();
|
|
}
|
|
};</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_rxjava" href="#_rxjava"></a>15.4 RxJava</h2></div></div></div><p>We registering a custom <a class="link" href="https://github.com/ReactiveX/RxJava/wiki/Plugins#rxjavaschedulershook" target="_top"><code class="literal">RxJavaSchedulersHook</code></a> that wraps all <code class="literal">Action0</code> instances in their Sleuth representative, which is called <code class="literal">TraceAction</code>.
|
|
The hook either starts or continues a span, depending on whether tracing was already going on before the Action was scheduled.
|
|
To disable the custom <code class="literal">RxJavaSchedulersHook</code>, set the <code class="literal">spring.sleuth.rxjava.schedulers.hook.enabled</code> to <code class="literal">false</code>.</p><p>You can define a list of regular expressions for thread names for which you do not want spans to be created.
|
|
To do so, provide a comma-separated list of regular expressions in the <code class="literal">spring.sleuth.rxjava.schedulers.ignoredthreads</code> property.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>The suggest approach to reactive programming and Sleuth is to use
|
|
the Reactor support.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http_integration" href="#_http_integration"></a>15.5 HTTP integration</h2></div></div></div><p>Features from this section can be disabled by setting the <code class="literal">spring.sleuth.web.enabled</code> property with value equal to <code class="literal">false</code>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_http_filter" href="#_http_filter"></a>15.5.1 HTTP Filter</h3></div></div></div><p>Through the <code class="literal">TracingFilter</code>, all sampled incoming requests result in creation of a Span.
|
|
That Span’s name is <code class="literal">http:</code> + the path to which the request was sent.
|
|
For example, if the request was sent to <code class="literal">/this/that</code> then the name will be <code class="literal">http:/this/that</code>.
|
|
You can configure which URIs you would like to skip by setting the <code class="literal">spring.sleuth.web.skipPattern</code> property.
|
|
If you have <code class="literal">ManagementServerProperties</code> on classpath, its value of <code class="literal">contextPath</code> gets appended to the provided skip pattern.
|
|
If you want to reuse the Sleuth’s default skip patterns and just append your own, pass those patterns by using the <code class="literal">spring.sleuth.web.additionalSkipPattern</code>.</p><p>By default, all the spring boot actuator endpoints are automatically added to the skip pattern.
|
|
If you want to disable this behaviour set <code class="literal">spring.sleuth.web.ignore-auto-configured-skip-patterns</code>
|
|
to <code class="literal">true</code>.</p><p>To change the order of tracing filter registration, please set the
|
|
<code class="literal">spring.sleuth.web.filter-order</code> property.</p><p>To disable the filter that logs uncaught exceptions you can disable the
|
|
<code class="literal">spring.sleuth.web.exception-throwing-filter-enabled</code> property.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_handlerinterceptor" href="#_handlerinterceptor"></a>15.5.2 HandlerInterceptor</h3></div></div></div><p>Since we want the span names to be precise, we use a <code class="literal">TraceHandlerInterceptor</code> that either wraps an existing <code class="literal">HandlerInterceptor</code> or is added directly to the list of existing <code class="literal">HandlerInterceptors</code>.
|
|
The <code class="literal">TraceHandlerInterceptor</code> adds a special request attribute to the given <code class="literal">HttpServletRequest</code>.
|
|
If the the <code class="literal">TracingFilter</code> does not see this attribute, it creates a "<code class="literal">fallback</code>" span, which is an additional span created on the server side so that the trace is presented properly in the UI.
|
|
If that happens, there is probably missing instrumentation.
|
|
In that case, please file an issue in Spring Cloud Sleuth.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_async_servlet_support" href="#_async_servlet_support"></a>15.5.3 Async Servlet support</h3></div></div></div><p>If your controller returns a <code class="literal">Callable</code> or a <code class="literal">WebAsyncTask</code>, Spring Cloud Sleuth continues the existing span instead of creating a new one.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_webflux_support" href="#_webflux_support"></a>15.5.4 WebFlux support</h3></div></div></div><p>Through <code class="literal">TraceWebFilter</code>, all sampled incoming requests result in creation of a Span.
|
|
That Span’s name is <code class="literal">http:</code> + the path to which the request was sent.
|
|
For example, if the request was sent to <code class="literal">/this/that</code>, the name is <code class="literal">http:/this/that</code>.
|
|
You can configure which URIs you would like to skip by using the <code class="literal">spring.sleuth.web.skipPattern</code> property.
|
|
If you have <code class="literal">ManagementServerProperties</code> on the classpath, its value of <code class="literal">contextPath</code> gets appended to the provided skip pattern.
|
|
If you want to reuse Sleuth’s default skip patterns and append your own, pass those patterns by using the <code class="literal">spring.sleuth.web.additionalSkipPattern</code>.</p><p>To change the order of tracing filter registration, please set the
|
|
<code class="literal">spring.sleuth.web.filter-order</code> property.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_dubbo_rpc_support" href="#_dubbo_rpc_support"></a>15.5.5 Dubbo RPC support</h3></div></div></div><p>Via the integration with Brave, Spring Cloud Sleuth supports <a class="link" href="https://dubbo.apache.org/" target="_top">Dubbo</a>.
|
|
It’s enough to add the <code class="literal">brave-instrumentation-dubbo-rpc</code> dependency:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>io.zipkin.brave<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></groupId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><artifactId></span>brave-instrumentation-dubbo-rpc<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span></pre><p>You need to also set a <code class="literal">dubbo.properties</code> file with the following contents:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">dubbo.provider.filter</span>=tracing
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">dubbo.consumer.filter</span>=tracing</pre><p>You can read more about Brave - Dubbo integration <a class="link" href="https://github.com/openzipkin/brave/tree/master/instrumentation/dubbo-rpc" target="_top">here</a>.
|
|
An example of Spring Cloud Sleuth and Dubbo can be found <a class="link" href="https://github.com/openzipkin/sleuth-webmvc-example/compare/add-dubbo-tracing" target="_top">here</a>.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http_client_integration" href="#_http_client_integration"></a>15.6 HTTP Client Integration</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_synchronous_rest_template" href="#_synchronous_rest_template"></a>15.6.1 Synchronous Rest Template</h3></div></div></div><p>We inject a <code class="literal">RestTemplate</code> interceptor to ensure that all the tracing information is passed to the requests.
|
|
Each time a call is made, a new Span is created.
|
|
It gets closed upon receiving the response.
|
|
To block the synchronous <code class="literal">RestTemplate</code> features, set <code class="literal">spring.sleuth.web.client.enabled</code> to <code class="literal">false</code>.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>You have to register <code class="literal">RestTemplate</code> as a bean so that the interceptors get injected.
|
|
If you create a <code class="literal">RestTemplate</code> instance with a <code class="literal">new</code> keyword, the instrumentation does NOT work.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_asynchronous_rest_template" href="#_asynchronous_rest_template"></a>15.6.2 Asynchronous Rest Template</h3></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Starting with Sleuth <code class="literal">2.0.0</code>, we no longer register a bean of <code class="literal">AsyncRestTemplate</code> type.
|
|
It is up to you to create such a bean.
|
|
Then we instrument it.</p></td></tr></table></div><p>To block the <code class="literal">AsyncRestTemplate</code> features, set <code class="literal">spring.sleuth.web.async.client.enabled</code> to <code class="literal">false</code>.
|
|
To disable creation of the default <code class="literal">TraceAsyncClientHttpRequestFactoryWrapper</code>, set <code class="literal">spring.sleuth.web.async.client.factory.enabled</code>
|
|
to <code class="literal">false</code>.
|
|
If you do not want to create <code class="literal">AsyncRestClient</code> at all, set <code class="literal">spring.sleuth.web.async.client.template.enabled</code> to <code class="literal">false</code>.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_multiple_asynchronous_rest_templates" href="#_multiple_asynchronous_rest_templates"></a>Multiple Asynchronous Rest Templates</h4></div></div></div><p>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 <code class="literal">AsyncRestTemplate</code>:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableAutoConfiguration</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> Config {
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Bean(name = "customAsyncRestTemplate")</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> AsyncRestTemplate traceAsyncRestTemplate() {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> AsyncRestTemplate(asyncClientFactory(),
|
|
clientHttpRequestFactory());
|
|
}
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> ClientHttpRequestFactory clientHttpRequestFactory() {
|
|
ClientHttpRequestFactory clientHttpRequestFactory = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> CustomClientHttpRequestFactory();
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// CUSTOMIZE HERE</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> clientHttpRequestFactory;
|
|
}
|
|
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> AsyncClientHttpRequestFactory asyncClientFactory() {
|
|
AsyncClientHttpRequestFactory factory = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> CustomAsyncClientHttpRequestFactory();
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// CUSTOMIZE HERE</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> factory;
|
|
}
|
|
|
|
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_webclient" href="#_webclient"></a>15.6.3 <code class="literal">WebClient</code></h3></div></div></div><p>We inject a <code class="literal">ExchangeFilterFunction</code> implementation that creates a span and, through on-success and on-error callbacks, takes care of closing client-side spans.</p><p>To block this feature, set <code class="literal">spring.sleuth.web.client.enabled</code> to <code class="literal">false</code>.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>You have to register <code class="literal">WebClient</code> as a bean so that the tracing instrumentation gets applied.
|
|
If you create a <code class="literal">WebClient</code> instance with a <code class="literal">new</code> keyword, the instrumentation does NOT work.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_traverson" href="#_traverson"></a>15.6.4 Traverson</h3></div></div></div><p>If you use the <a class="link" href="https://docs.spring.io/spring-hateoas/docs/current/reference/html/#client.traverson" target="_top">Traverson</a> library, you can inject a <code class="literal">RestTemplate</code> as a bean into your Traverson object.
|
|
Since <code class="literal">RestTemplate</code> is already intercepted, you get full support for tracing in your client. The following pseudo code
|
|
shows how to do that:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation> RestTemplate restTemplate;
|
|
|
|
Traverson traverson = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Traverson(URI.create(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"http://some/address"</span>),
|
|
MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8).setRestOperations(restTemplate);
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// use Traverson</span></pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_apache_httpclientbuilder_and_httpasyncclientbuilder" href="#_apache_httpclientbuilder_and_httpasyncclientbuilder"></a>15.6.5 Apache <code class="literal">HttpClientBuilder</code> and <code class="literal">HttpAsyncClientBuilder</code></h3></div></div></div><p>We instrument the <code class="literal">HttpClientBuilder</code> and <code class="literal">HttpAsyncClientBuilder</code> so that
|
|
tracing context gets injected to the sent requests.</p><p>To block these features, set <code class="literal">spring.sleuth.web.client.enabled</code> to <code class="literal">false</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_netty_httpclient" href="#_netty_httpclient"></a>15.6.6 Netty <code class="literal">HttpClient</code></h3></div></div></div><p>We instrument the Netty’s <code class="literal">HttpClient</code>.</p><p>To block this feature, set <code class="literal">spring.sleuth.web.client.enabled</code> to <code class="literal">false</code>.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>You have to register <code class="literal">HttpClient</code> as a bean so that the instrumentation happens.
|
|
If you create a <code class="literal">HttpClient</code> instance with a <code class="literal">new</code> keyword, the instrumentation does NOT work.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_userinforesttemplatecustomizer" href="#_userinforesttemplatecustomizer"></a>15.6.7 <code class="literal">UserInfoRestTemplateCustomizer</code></h3></div></div></div><p>We instrument the Spring Security’s <code class="literal">UserInfoRestTemplateCustomizer</code>.</p><p>To block this feature, set <code class="literal">spring.sleuth.web.client.enabled</code> to <code class="literal">false</code>.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_feign" href="#_feign"></a>15.7 Feign</h2></div></div></div><p>By default, Spring Cloud Sleuth provides integration with Feign through <code class="literal">TraceFeignClientAutoConfiguration</code>.
|
|
You can disable it entirely by setting <code class="literal">spring.sleuth.feign.enabled</code> to <code class="literal">false</code>.
|
|
If you do so, no Feign-related instrumentation take place.</p><p>Part of Feign instrumentation is done through a <code class="literal">FeignBeanPostProcessor</code>.
|
|
You can disable it by setting <code class="literal">spring.sleuth.feign.processor.enabled</code> to <code class="literal">false</code>.
|
|
If you set it to <code class="literal">false</code>, Spring Cloud Sleuth does not instrument any of your custom Feign components.
|
|
However, all the default instrumentation is still there.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_grpc" href="#_grpc"></a>15.8 gRPC</h2></div></div></div><p>Spring Cloud Sleuth provides instrumentation for <a class="link" href="https://grpc.io/" target="_top">gRPC</a> through <code class="literal">TraceGrpcAutoConfiguration</code>. You can disable it entirely by setting <code class="literal">spring.sleuth.grpc.enabled</code> to <code class="literal">false</code>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_variant_1" href="#_variant_1"></a>15.8.1 Variant 1</h3></div></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_dependencies" href="#_dependencies"></a>Dependencies</h4></div></div></div><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>The gRPC integration relies on two external libraries to instrument clients and servers and both of those libraries must be on the class path to enable the instrumentation.</p></td></tr></table></div><p>Maven:</p><pre class="screen"> <dependency>
|
|
<groupId>io.github.lognet</groupId>
|
|
<artifactId>grpc-spring-boot-starter</artifactId>
|
|
</dependency>
|
|
<dependency>
|
|
<groupId>io.zipkin.brave</groupId>
|
|
<artifactId>brave-instrumentation-grpc</artifactId>
|
|
</dependency></pre><p>Gradle:</p><pre class="screen"> compile("io.github.lognet:grpc-spring-boot-starter")
|
|
compile("io.zipkin.brave:brave-instrumentation-grpc")</pre></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_server_instrumentation" href="#_server_instrumentation"></a>Server Instrumentation</h4></div></div></div><p>Spring Cloud Sleuth leverages grpc-spring-boot-starter to register Brave’s gRPC server interceptor with all services annotated with <code class="literal">@GRpcService</code>.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_client_instrumentation" href="#_client_instrumentation"></a>Client Instrumentation</h4></div></div></div><p>gRPC clients leverage a <code class="literal">ManagedChannelBuilder</code> to construct a <code class="literal">ManagedChannel</code> used to communicate to the gRPC server. The native <code class="literal">ManagedChannelBuilder</code> provides static methods as entry points for construction of <code class="literal">ManagedChannel</code> instances, however, this mechanism is outside the influence of the Spring application context.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Spring Cloud Sleuth provides a <code class="literal">SpringAwareManagedChannelBuilder</code> that can be customized through the Spring application context and injected by gRPC clients. <span class="strong"><strong>This builder must be used when creating <code class="literal">ManagedChannel</code> instances.</strong></span></p></td></tr></table></div><p>Sleuth creates a <code class="literal">TracingManagedChannelBuilderCustomizer</code> which inject Brave’s client interceptor into the <code class="literal">SpringAwareManagedChannelBuilder</code>.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_variant_2" href="#_variant_2"></a>15.8.2 Variant 2</h3></div></div></div><p><a class="link" href="https://github.com/yidongnan/grpc-spring-boot-starter" target="_top">Grpc Spring Boot Starter</a> automatically detects the presence of Spring Cloud Sleuth and brave’s instrumentation for gRPC and registers the necessary client and/or server tooling.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_asynchronous_communication" href="#_asynchronous_communication"></a>15.9 Asynchronous Communication</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_async_annotated_methods" href="#_async_annotated_methods"></a>15.9.1 <code class="literal">@Async</code> Annotated methods</h3></div></div></div><p>In Spring Cloud Sleuth, we instrument async-related components so that the tracing information is passed between threads.
|
|
You can disable this behavior by setting the value of <code class="literal">spring.sleuth.async.enabled</code> to <code class="literal">false</code>.</p><p>If you annotate your method with <code class="literal">@Async</code>, we automatically create a new Span with the following characteristics:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">If the method is annotated with <code class="literal">@SpanName</code>, the value of the annotation is the Span’s name.</li><li class="listitem">If the method is not annotated with <code class="literal">@SpanName</code>, the Span name is the annotated method name.</li><li class="listitem">The span is tagged with the method’s class name and method name.</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_scheduled_annotated_methods" href="#_scheduled_annotated_methods"></a>15.9.2 <code class="literal">@Scheduled</code> Annotated Methods</h3></div></div></div><p>In Spring Cloud Sleuth, we instrument scheduled method execution so that the tracing information is passed between threads.
|
|
You can disable this behavior by setting the value of <code class="literal">spring.sleuth.scheduled.enabled</code> to <code class="literal">false</code>.</p><p>If you annotate your method with <code class="literal">@Scheduled</code>, we automatically create a new span with the following characteristics:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">The span name is the annotated method name.</li><li class="listitem">The span is tagged with the method’s class name and method name.</li></ul></div><p>If you want to skip span creation for some <code class="literal">@Scheduled</code> annotated classes, you can set the <code class="literal">spring.sleuth.scheduled.skipPattern</code> with a regular expression that matches the fully qualified name of the <code class="literal">@Scheduled</code> annotated class.
|
|
If you use <code class="literal">spring-cloud-sleuth-stream</code> and <code class="literal">spring-cloud-netflix-hystrix-stream</code> together, a span is created for each Hystrix metrics and sent to Zipkin.
|
|
This behavior may be annoying. That’s why, by default, <code class="literal">spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_executor_executorservice_and_scheduledexecutorservice" href="#_executor_executorservice_and_scheduledexecutorservice"></a>15.9.3 Executor, ExecutorService, and ScheduledExecutorService</h3></div></div></div><p>We provide <code class="literal">LazyTraceExecutor</code>, <code class="literal">TraceableExecutorService</code>, and <code class="literal">TraceableScheduledExecutorService</code>. Those implementations create spans each time a new task is submitted, invoked, or scheduled.</p><p>The following example shows how to pass tracing information with <code class="literal">TraceableExecutorService</code> when working with <code class="literal">CompletableFuture</code>:</p><pre class="programlisting">CompletableFuture<Long> completableFuture = CompletableFuture.supplyAsync(() -> {
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// perform some logic</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">1</xslthl:number>_<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">000</xslthl:number>_<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">000L</xslthl:number>;
|
|
}, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceableExecutorService(beanFactory, executorService,
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// 'calculateTax' explicitly names the span - this param is optional</span>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateTax"</span>));</pre><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>Sleuth does not work with <code class="literal">parallelStream()</code> out of the box.
|
|
If you want to have the tracing information propagated through the stream, you have to use the approach with <code class="literal">supplyAsync(...)</code>, as shown earlier.</p></td></tr></table></div><p>If there are beans that implement the <code class="literal">Executor</code> interface that you would like
|
|
to exclude from span creation, you can use the <code class="literal">spring.sleuth.async.ignored-beans</code>
|
|
property where you can provide a list of bean names.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_customization_of_executors" href="#_customization_of_executors"></a>Customization of Executors</h4></div></div></div><p>Sometimes, you need to set up a custom instance of the <code class="literal">AsyncExecutor</code>.
|
|
The following example shows how to set up such a custom <code class="literal">Executor</code>:</p><pre class="programlisting"><xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Configuration</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableAutoConfiguration</xslthl:annotation>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@EnableAsync</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// add the infrastructure role to ensure that the bean gets auto-proxied</span>
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Role(BeanDefinition.ROLE_INFRASTRUCTURE)</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">static</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> CustomExecutorConfig <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> AsyncConfigurerSupport {
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Autowired</xslthl:annotation>
|
|
BeanFactory beanFactory;
|
|
|
|
<xslthl:annotation xmlns:xslthl="http://xslthl.sourceforge.net/">@Override</xslthl:annotation>
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Executor getAsyncExecutor() {
|
|
ThreadPoolTaskExecutor executor = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> ThreadPoolTaskExecutor();
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// CUSTOMIZE HERE</span>
|
|
executor.setCorePoolSize(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">7</xslthl:number>);
|
|
executor.setMaxPoolSize(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">42</xslthl:number>);
|
|
executor.setQueueCapacity(<xslthl:number xmlns:xslthl="http://xslthl.sourceforge.net/">11</xslthl:number>);
|
|
executor.setThreadNamePrefix(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"MyExecutor-"</span>);
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// DON'T FORGET TO INITIALIZE</span>
|
|
executor.initialize();
|
|
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> LazyTraceExecutor(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.beanFactory, executor);
|
|
}
|
|
|
|
}</pre><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Tip"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="images/tip.png"></td><th align="left">Tip</th></tr><tr><td align="left" valign="top"><p>To ensure that your configuration gets post processed, remember
|
|
to add the <code class="literal">@Role(BeanDefinition.ROLE_INFRASTRUCTURE)</code> on your
|
|
<code class="literal">@Configuration</code> class</p></td></tr></table></div></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_messaging" href="#_messaging"></a>15.10 Messaging</h2></div></div></div><p>Features from this section can be disabled by setting the <code class="literal">spring.sleuth.messaging.enabled</code> property with value equal to <code class="literal">false</code>.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spring_integration_and_spring_cloud_stream" href="#_spring_integration_and_spring_cloud_stream"></a>15.10.1 Spring Integration and Spring Cloud Stream</h3></div></div></div><p>Spring Cloud Sleuth integrates with <a class="link" href="https://projects.spring.io/spring-integration/" target="_top">Spring Integration</a>.
|
|
It creates spans for publish and subscribe events.
|
|
To disable Spring Integration instrumentation, set <code class="literal">spring.sleuth.integration.enabled</code> to <code class="literal">false</code>.</p><p>You can provide the <code class="literal">spring.sleuth.integration.patterns</code> pattern to explicitly provide the names of channels that you want to include for tracing.
|
|
By default, all channels but <code class="literal">hystrixStreamOutput</code> channel are included.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>When using the <code class="literal">Executor</code> to build a Spring Integration <code class="literal">IntegrationFlow</code>, you must use the untraced version of the <code class="literal">Executor</code>.
|
|
Decorating the Spring Integration Executor Channel with <code class="literal">TraceableExecutorService</code> causes the spans to be improperly closed.</p></td></tr></table></div><p>If you want to customize the way tracing context is read from and written to message headers,
|
|
it’s enough for you to register beans of types:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">Propagation.Setter<MessageHeaderAccessor, String></code> - for writing headers to the message</li><li class="listitem"><code class="literal">Propagation.Getter<MessageHeaderAccessor, String></code> - for reading headers from the message</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spring_rabbitmq" href="#_spring_rabbitmq"></a>15.10.2 Spring RabbitMq</h3></div></div></div><p>We instrument the <code class="literal">RabbitTemplate</code> so that tracing headers get injected
|
|
into the message.</p><p>To block this feature, set <code class="literal">spring.sleuth.messaging.rabbit.enabled</code> to <code class="literal">false</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spring_kafka" href="#_spring_kafka"></a>15.10.3 Spring Kafka</h3></div></div></div><p>We instrument the Spring Kafka’s <code class="literal">ProducerFactory</code> and <code class="literal">ConsumerFactory</code>
|
|
so that tracing headers get injected into the created Spring Kafka’s
|
|
<code class="literal">Producer</code> and <code class="literal">Consumer</code>.</p><p>To block this feature, set <code class="literal">spring.sleuth.messaging.kafka.enabled</code> to <code class="literal">false</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_spring_jms" href="#_spring_jms"></a>15.10.4 Spring JMS</h3></div></div></div><p>We instrument the <code class="literal">JmsTemplate</code> so that tracing headers get injected
|
|
into the message. We also support <code class="literal">@JmsListener</code> annotated methods on the consumer side.</p><p>To block this feature, set <code class="literal">spring.sleuth.messaging.jms.enabled</code> to <code class="literal">false</code>.</p><div class="important" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Important"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="images/important.png"></td><th align="left">Important</th></tr><tr><td align="left" valign="top"><p>We don’t support baggage propagation for JMS</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_zuul" href="#_zuul"></a>15.11 Zuul</h2></div></div></div><p>We instrument the Zuul Ribbon integration by enriching the Ribbon requests with tracing information.
|
|
To disable Zuul support, set the <code class="literal">spring.sleuth.zuul.enabled</code> property to <code class="literal">false</code>.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__zipkin_stream_span_consumer.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__running_examples.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">14. Zipkin Stream Span Consumer </td><td width="20%" align="center"><a accesskey="h" href="multi_spring-cloud-sleuth.html">Home</a></td><td width="40%" align="right" valign="top"> 16. Running examples</td></tr></table></div></body></html> |