Sync docs from master to gh-pages
This commit is contained in:
20
multi/multi__current_span.html
Normal file
20
multi/multi__current_span.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>7. Current Span</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__current_tracing_component.html" title="6. Current Tracing Component"><link rel="next" href="multi__instrumentation.html" title="8. Instrumentation"></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">7. Current Span</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__current_tracing_component.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__instrumentation.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_current_span" href="#_current_span"></a>7. Current Span</h1></div></div></div><p>Brave supports a "current span" concept which represents the in-flight
|
||||
operation. <code class="literal">Tracer.currentSpan()</code> can be used to add custom tags to a
|
||||
span and <code class="literal">Tracer.nextSpan()</code> can be used to create a child of whatever
|
||||
is in-flight.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_setting_a_span_in_scope_manually" href="#_setting_a_span_in_scope_manually"></a>7.1 Setting a span in scope manually</h2></div></div></div><p>When writing new instrumentation, it is important to place a span you
|
||||
created in scope as the current span. Not only does this allow users to
|
||||
access it with <code class="literal">Tracer.currentSpan()</code>, but it also allows customizations
|
||||
like SLF4J MDC to see the current trace IDs.</p><p><code class="literal">Tracer.withSpanInScope(Span)</code> facilitates this and is most conveniently
|
||||
employed via the try-with-resources idiom. Whenever external code might
|
||||
be invoked (such as proceeding an interceptor or otherwise), place the
|
||||
span in scope like this.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> (SpanInScope ws = tracer.withSpanInScope(span)) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> inboundRequest.invoke();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> { <span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// note the scope is independent of the span</span>
|
||||
span.finish();
|
||||
}</pre><p>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 this, simply pass null to <code class="literal">withSpanInScope</code>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> (SpanInScope cleared = tracer.withSpanInScope(null)) {
|
||||
startBackgroundThread();
|
||||
}</pre></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__current_tracing_component.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__instrumentation.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6. Current Tracing Component </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"> 8. Instrumentation</td></tr></table></div></body></html>
|
||||
9
multi/multi__current_tracing_component.html
Normal file
9
multi/multi__current_tracing_component.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>6. Current Tracing Component</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__propagation.html" title="5. Propagation"><link rel="next" href="multi__current_span.html" title="7. Current Span"></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">6. Current Tracing Component</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__propagation.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__current_span.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_current_tracing_component" href="#_current_tracing_component"></a>6. Current Tracing Component</h1></div></div></div><p>Brave supports a "current tracing component" concept which should only
|
||||
be used when you have no other means to get a reference. This was made
|
||||
for JDBC connections, as they often initialize prior to the tracing
|
||||
component.</p><p>The most recent tracing component instantiated is available via
|
||||
<code class="literal">Tracing.current()</code>. You there’s also a shortcut to get only the tracer
|
||||
via <code class="literal">Tracing.currentTracer()</code>. If you use either of these methods, do
|
||||
noot cache the result. Instead, look them up each time you need them.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__propagation.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__current_span.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Propagation </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"> 7. Current Span</td></tr></table></div></body></html>
|
||||
@@ -1,149 +1,40 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>9. Customizations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__managing_spans_with_annotations.html" title="8. Managing spans with annotations"><link rel="next" href="multi__sending_spans_to_zipkin.html" title="10. Sending spans to Zipkin"></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">9. Customizations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__managing_spans_with_annotations.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__sending_spans_to_zipkin.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_customizations" href="#_customizations"></a>9. Customizations</h1></div></div></div><p>Thanks to the <code class="literal">SpanInjector</code> and <code class="literal">SpanExtractor</code> you can customize the way spans
|
||||
are created and propagated.</p><p>There are currently two built-in ways to pass tracing information between processes:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">via Spring Integration</li><li class="listitem">via HTTP</li></ul></div><p>Span ids are extracted from Zipkin-compatible (B3) headers (either <code class="literal">Message</code>
|
||||
or HTTP headers), to start or join an existing trace. Trace information is
|
||||
injected into any outbound requests so the next hop can extract them.</p><p>The key change in comparison to the previous versions of Sleuth is that Sleuth is implementing
|
||||
the Open Tracing’s <code class="literal">TextMap</code> notion. In Sleuth it’s called <code class="literal">SpanTextMap</code>. Basically the idea
|
||||
is that any means of communication (e.g. message, http request, etc.) can be abstracted via
|
||||
a <code class="literal">SpanTextMap</code>. This abstraction defines how one can insert data into the carrier and
|
||||
how to retrieve it from there. Thanks to this if you want to instrument a new HTTP library
|
||||
that uses a <code class="literal">FooRequest</code> as a mean of sending HTTP requests then you have to create an
|
||||
implementation of a <code class="literal">SpanTextMap</code> that delegates calls to <code class="literal">FooRequest</code> in terms of retrieval
|
||||
and insertion of HTTP headers.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_spring_integration" href="#_spring_integration"></a>9.1 Spring Integration</h2></div></div></div><p>For Spring Integration there are 2 interfaces responsible for creation of a Span from a <code class="literal">Message</code>.
|
||||
These are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">MessagingSpanTextMapExtractor</code></li><li class="listitem"><code class="literal">MessagingSpanTextMapInjector</code></li></ul></div><p>You can override them by providing your own implementation.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http" href="#_http"></a>9.2 HTTP</h2></div></div></div><p>For HTTP there are 2 interfaces responsible for creation of a Span from a <code class="literal">Message</code>.
|
||||
These are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">HttpSpanExtractor</code></li><li class="listitem"><code class="literal">HttpSpanInjector</code></li></ul></div><p>You can override them by providing your own implementation.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_example" href="#_example"></a>9.3 Example</h2></div></div></div><p>Let’s assume that instead of the standard Zipkin compatible tracing HTTP header names
|
||||
you have</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">for trace id - <code class="literal">correlationId</code></li><li class="listitem">for span id - <code class="literal">mySpanId</code></li></ul></div><p>This is a an example of a <code class="literal">SpanExtractor</code></p><pre class="programlisting"><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> CustomHttpSpanExtractor <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> HttpSpanExtractor {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Span joinTrace(SpanTextMap carrier) {
|
||||
Map<String, String> map = TextMapUtil.asMap(carrier);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">long</span> traceId = Span.hexToId(map.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"correlationid"</span>));
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">long</span> spanId = Span.hexToId(map.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"myspanid"</span>));
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// extract all necessary headers</span>
|
||||
Span.SpanBuilder builder = Span.builder().traceId(traceId).spanId(spanId);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// build rest of the Span</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
<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> CustomHttpSpanInjector <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> HttpSpanInjector {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<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> inject(Span span, SpanTextMap carrier) {
|
||||
carrier.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"correlationId"</span>, span.traceIdString());
|
||||
carrier.put(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"mySpanId"</span>, Span.idToHex(span.getSpanId()));
|
||||
}
|
||||
}</pre><p>And you could register it like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
HttpSpanInjector customHttpSpanInjector() {
|
||||
<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> CustomHttpSpanInjector();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
HttpSpanExtractor customHttpSpanExtractor() {
|
||||
<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> CustomHttpSpanExtractor();
|
||||
}</pre><p>Spring Cloud Sleuth does not add trace/span related headers to the Http Response for security reasons. If you need the headers then a custom <code class="literal">SpanInjector</code>
|
||||
that injects the headers into the Http Response and a Servlet filter which makes use of this can be added the following way:</p><pre class="programlisting"><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> CustomHttpServletResponseSpanInjector <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> ZipkinHttpSpanInjector {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<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> inject(Span span, SpanTextMap carrier) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">super</span>.inject(span, carrier);
|
||||
carrier.put(Span.TRACE_ID_NAME, span.traceIdString());
|
||||
carrier.put(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
|
||||
}
|
||||
}
|
||||
|
||||
<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> HttpResponseInjectingTraceFilter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> GenericFilterBean {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Tracer tracer;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> HttpSpanInjector spanInjector;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> HttpResponseInjectingTraceFilter(Tracer tracer, HttpSpanInjector spanInjector) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer = tracer;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.spanInjector = spanInjector;
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<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> doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> IOException, ServletException {
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
Span currentSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.getCurrentSpan();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.spanInjector.inject(currentSpan, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HttpServletResponseTextMap(response));
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> HttpServletResponseTextMap <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> SpanTextMap {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> HttpServletResponse delegate;
|
||||
|
||||
HttpServletResponseTextMap(HttpServletResponse delegate) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.delegate = delegate;
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Iterator<Map.Entry<String, String>> iterator() {
|
||||
Map<String, String> map = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> HashMap<>();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> (String header : <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.delegate.getHeaderNames()) {
|
||||
map.put(header, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.delegate.getHeader(header));
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> map.entrySet().iterator();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<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> put(String key, String value) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.delegate.addHeader(key, value);
|
||||
}
|
||||
}
|
||||
}</pre><p>And you could register them like this:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em> HttpSpanInjector customHttpServletResponseSpanInjector() {
|
||||
<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> CustomHttpServletResponseSpanInjector();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
HttpResponseInjectingTraceFilter responseInjectingTraceFilter(Tracer tracer) {
|
||||
<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> HttpResponseInjectingTraceFilter(tracer, customHttpServletResponseSpanInjector());
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_tracefilter" href="#_tracefilter"></a>9.4 TraceFilter</h2></div></div></div><p>You can also modify the behaviour of the <code class="literal">TraceFilter</code> - the component that is responsible
|
||||
<title>12. Customizations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__managing_spans_with_annotations.html" title="11. Managing spans with annotations"><link rel="next" href="multi__sending_spans_to_zipkin.html" title="13. Sending spans to Zipkin"></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">12. Customizations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__managing_spans_with_annotations.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__sending_spans_to_zipkin.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_customizations" href="#_customizations"></a>12. Customizations</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_spring_integration" href="#_spring_integration"></a>12.1 Spring Integration</h2></div></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http" href="#_http"></a>12.2 HTTP</h2></div></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_tracefilter" href="#_tracefilter"></a>12.3 TraceFilter</h2></div></div></div><p>You can also modify the behaviour of the <code class="literal">TraceFilter</code> - 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 <code class="literal">TraceFilter</code> bean.</p><p>In the following example we will register the <code class="literal">TraceFilter</code> bean and we will add the
|
||||
<code class="literal">ZIPKIN-TRACE-ID</code> response header containing the current Span’s trace id. Also we will
|
||||
add to the Span a tag with key <code class="literal">custom</code> and a value <code class="literal">tag</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
TraceFilter myTraceFilter(BeanFactory beanFactory, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Tracer tracer) {
|
||||
<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> TraceFilter(beanFactory) {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">protected</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> addResponseTags(HttpServletResponse response,
|
||||
Throwable e) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// execute the default behaviour</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">super</span>.addResponseTags(response, e);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// for readability we're returning trace id in a hex form</span>
|
||||
response.addHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"ZIPKIN-TRACE-ID"</span>,
|
||||
Span.idToHex(tracer.getCurrentSpan().getTraceId()));
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// we can also add some custom tags</span>
|
||||
tracer.addTag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"custom"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tag"</span>);
|
||||
}
|
||||
};
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_sa_tag_in_zipkin" href="#_custom_sa_tag_in_zipkin"></a>9.5 Custom SA tag in Zipkin</h2></div></div></div><p>Sometimes you want to create a manual Span that will wrap a call to an external service which is not instrumented.
|
||||
What you can do is to create a span with the <code class="literal">peer.service</code> tag that will contain a value of the service that you want to call.
|
||||
Below you can see an example of a call to Redis that is wrapped in such a span.</p><pre class="programlisting">Span span = tracer.createSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"redis"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"redis.op"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"get"</span>);
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"lc"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"redis"</span>);
|
||||
span.logEvent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"cs"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// call redis service e.g</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// return (SomeObj) redisTemplate.opsForHash().get("MYHASH", someObjKey);</span>
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"peer.service"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"redis"</span>);
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"peer.ipv4"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1.2.3.4"</span>);
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"peer.port"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"1234"</span>);
|
||||
span.logEvent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"cr"</span>);
|
||||
span.stop();
|
||||
}</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>Remember not to add both <code class="literal">peer.service</code> tag and the <code class="literal">SA</code> tag! You have to add only <code class="literal">peer.service</code>.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_service_name" href="#_custom_service_name"></a>9.6 Custom service name</h2></div></div></div><p>By default Sleuth assumes that when you send a span to Zipkin, you want the span’s service name
|
||||
add to the Span a tag with key <code class="literal">custom</code> and a value <code class="literal">tag</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Component</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Order(TraceFilter.ORDER + 1)</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyFilter <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">extends</span> GenericFilterBean {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Tracer tracer;
|
||||
|
||||
MyFilter(Tracer tracer) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer = tracer;
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <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> doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> IOException, ServletException {
|
||||
Span currentSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.currentSpan();
|
||||
then(currentSpan).isNotNull();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// for readability we're returning trace id in a hex form</span>
|
||||
((HttpServletResponse) response)
|
||||
.addHeader(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"ZIPKIN-TRACE-ID"</span>,
|
||||
currentSpan.context().traceIdString());
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// we can also add some custom tags</span>
|
||||
currentSpan.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"custom"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tag"</span>);
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_service_name" href="#_custom_service_name"></a>12.4 Custom service name</h2></div></div></div><p>By default Sleuth assumes that when you send a span to Zipkin, you want the span’s service name
|
||||
to be equal to <code class="literal">spring.application.name</code> value. That’s 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 it’s enough to just pass the following property
|
||||
to your application to override that value (example for <code class="literal">foo</code> service name):</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.zipkin.service.name</span>: foo</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customization_of_reported_spans" href="#_customization_of_reported_spans"></a>9.7 Customization of reported spans</h2></div></div></div><p>Before reporting spans to e.g. Zipkin you can be interested in modifying that span in some way.
|
||||
You can achieve that by using the <code class="literal">SpanAdjuster</code> interface.</p><p>Example of usage:</p><p>In Sleuth we’re generating spans with a fixed name. Some users want to modify the name depending on values
|
||||
of tags. Implementation of the <code class="literal">SpanAdjuster</code> interface can be used to alter that name. Example:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
SpanAdjuster customSpanAdjuster() <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">{</span>
|
||||
return span -> span.toBuilder().name(scrub(span.getName())).build();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">}</span></pre><p>This will lead in changing the name of the reported span just before it gets sent to Zipkin.</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>Your <code class="literal">SpanReporter</code> should inject the <code class="literal">SpanAdjuster</code> and
|
||||
allow span manipulation before the actual reporting is done.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_host_locator" href="#_host_locator"></a>9.8 Host locator</h2></div></div></div><p>In order to define the host that is corresponding to a particular span we need to resolve the host name
|
||||
to your application to override that value (example for <code class="literal">foo</code> service name):</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.zipkin.service.name</span>: foo</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_customization_of_reported_spans" href="#_customization_of_reported_spans"></a>12.5 Customization of reported spans</h2></div></div></div><p>Before reporting spans to e.g. Zipkin you can be interested in modifying that span in some way.
|
||||
You can achieve that by using the <code class="literal">SpanAdjuster</code> interface.</p><p>In Sleuth we’re generating spans with a fixed name. Some users want to modify the name depending on values
|
||||
of tags. Implementation of the <code class="literal">SpanAdjuster</code> interface can be used to alter that name. Example:</p><p>Example. If you register two beans of <code class="literal">SpanAdjuster</code> type:</p><pre class="programlisting">Unresolved directive in spring-cloud-sleuth.adoc - include::../../../..<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/SpanAdjusterAspectTests.java[tags=adjuster,indent=0]</span></pre><p>This will lead in changing the name of the reported span to <code class="literal">foo bar</code>, just before it gets reported (e.g. to Zipkin).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_host_locator" href="#_host_locator"></a>12.6 Host locator</h2></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>This section is about defining <span class="strong"><strong>host</strong></span> from service discovery. It’s <span class="strong"><strong>NOT</strong></span>
|
||||
about finding Zipkin in service discovery.</p></td></tr></table></div><p>In order to define the host that is corresponding to a particular span we need to resolve the host name
|
||||
and port. The default approach is to take it from server properties. If those for some reason are not set
|
||||
then we’re trying to retrieve the host name from the network interfaces.</p><p>If you have the discovery client enabled and prefer to retrieve the host address from the registered
|
||||
instance in a service registry then you have to set the property (it’s applicable for both HTTP and
|
||||
Stream based span reporting).</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.zipkin.locator.discovery.enabled</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">true</span></pre></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__managing_spans_with_annotations.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__sending_spans_to_zipkin.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8. Managing spans with annotations </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"> 10. Sending spans to Zipkin</td></tr></table></div></body></html>
|
||||
Stream based span reporting).</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.zipkin.locator.discovery.enabled</span>: <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">true</span></pre></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__managing_spans_with_annotations.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__sending_spans_to_zipkin.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">11. Managing spans with annotations </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"> 13. Sending spans to Zipkin</td></tr></table></div></body></html>
|
||||
@@ -17,4 +17,110 @@ Configure the location of the service using <code class="literal">spring.zipkin.
|
||||
above. Other logging systems have to configure their own formatter to get the same result. The default is
|
||||
<code class="literal">logging.pattern.level</code> set to <code class="literal">%5p [${spring.zipkin.service.name:${spring.application.name:-}},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]</code>
|
||||
(this is a Spring Boot feature for logback users).
|
||||
<span class="strong"><strong>This means that if you’re not using SLF4J this pattern WILL NOT be automatically applied</strong></span>.</p></td></tr></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__additional_resources.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__sampling.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. Additional resources </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"> 4. Sampling</td></tr></table></div></body></html>
|
||||
<span class="strong"><strong>This means that if you’re not using SLF4J this pattern WILL NOT be automatically applied</strong></span>.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_introduction_to_brave" href="#_introduction_to_brave"></a>3.1 Introduction to Brave</h2></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 version <code class="literal">2.0.0</code> Spring Cloud Sleuth uses
|
||||
<a class="link" href="https://github.com/openzipkin/brave" target="_top">Brave</a> as the tracing library.
|
||||
For your convenience we’re embedding part of the Brave’s docs here.</p></td></tr></table></div><p>Brave is a library used to capture and report latency information about
|
||||
distributed operations to Zipkin. Most users won’t use Brave directly,
|
||||
rather libraries or frameworks than employ Brave on their behalf.</p><p>This module includes tracer creates and joins spans that model the
|
||||
latency of potentially distributed work. It also includes libraries to
|
||||
propagate the trace context over network boundaries, for example, via
|
||||
http headers.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_tracing" href="#_tracing"></a>3.1.1 Tracing</h3></div></div></div><p>Most importantly, you need a <code class="literal">brave.Tracer</code>, configured to [report to Zipkin]
|
||||
(<a class="link" href="https://github.com/openzipkin/zipkin-reporter-java" target="_top">https://github.com/openzipkin/zipkin-reporter-java</a>).</p><p>Here’s an example setup that sends trace data (spans) to Zipkin over
|
||||
http (as opposed to Kafka).</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> MyClass {
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">private</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">final</span> Tracer tracer;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Tracer will be autowired</span>
|
||||
MyClass(Tracer tracer) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer = tracer;
|
||||
}
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> doSth() {
|
||||
Span span = tracer.newTrace().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>).start();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</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>If your span contains a name greater than 50 chars, then that name will
|
||||
be truncated to 50 chars. Your names have to be explicit and concrete. Big names lead to
|
||||
latency issues and sometimes even thrown exceptions.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_tracing_2" href="#_tracing_2"></a>3.1.2 Tracing</h3></div></div></div><p>The tracer creates and joins spans that model the latency of potentially
|
||||
distributed work. It can employ sampling to reduce overhead in process
|
||||
or to reduce the amount of data sent to Zipkin.</p><p>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.</p><p>Spans have a context which includes trace identifiers that place it at
|
||||
the correct spot in the tree representing the distributed operation.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_local_tracing" href="#_local_tracing"></a>3.1.3 Local Tracing</h3></div></div></div><p>When tracing local code, just run it inside a span.</p><pre class="programlisting">Span span = tracer.newTrace().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>).start();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
doSomethingExpensive();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.finish();
|
||||
}</pre><p>In the above example, the span is the root of the trace. In many cases,
|
||||
you will be a part of an existing trace. When this is the case, call
|
||||
<code class="literal">newChild</code> instead of <code class="literal">newTrace</code></p><pre class="programlisting">Span span = tracer.newChild(root.context()).name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"encode"</span>).start();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
doSomethingExpensive();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.finish();
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_customizing_spans" href="#_customizing_spans"></a>3.1.4 Customizing spans</h3></div></div></div><p>Once you have a span, you can add tags to it, which can be used as lookup
|
||||
keys or details. For example, you might add a tag with your runtime
|
||||
version.</p><pre class="programlisting">span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"clnt/finagle.version"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"6.36.0"</span>);</pre><p>When exposing the ability to customize spans to third parties, prefer
|
||||
<code class="literal">brave.SpanCustomizer</code> as opposed to <code class="literal">brave.Span</code>. The former is simpler to
|
||||
understand and test, and doesn’t tempt users with span lifecycle hooks.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">interface</span> MyTraceCallback {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> request(Request request, SpanCustomizer customizer);
|
||||
}</pre><p>Since <code class="literal">brave.Span</code> implements <code class="literal">brave.SpanCustomizer</code>, it is just as easy for you
|
||||
to pass to users.</p><p>Ex.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">for</span> (MyTraceCallback callback : userCallbacks) {
|
||||
callback.request(request, span);
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_implicitly_looking_up_the_current_span" href="#_implicitly_looking_up_the_current_span"></a>3.1.5 Implicitly looking up the current span</h3></div></div></div><p>Sometimes you won’t know if a trace is in progress or not, and you don’t
|
||||
want users to do null checks. <code class="literal">brave.CurrentSpanCustomizer</code> adds to any
|
||||
span that’s in progress or drops data accordingly.</p><p>Ex.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// user code can then inject this without a chance of it being null.</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowire</span></em> SpanCustomizer span;
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> userCode() {
|
||||
span.annotate(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"tx.started"</span>);
|
||||
...
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_rpc_tracing" href="#_rpc_tracing"></a>3.1.6 RPC tracing</h3></div></div></div><p>Check for <a class="link" href="https://github.com/openzipkin/sleuth/tree/master/instrumentation" target="_top">instrumentation written here</a>
|
||||
and <a class="link" href="http://zipkin.io/pages/existing_instrumentations.html" target="_top">Zipkin’s list</a>
|
||||
before rolling your own RPC instrumentation!</p><p>RPC tracing is often done automatically by interceptors. Under the scenes,
|
||||
they add tags and events that relate to their role in an RPC operation.</p><p>Here’s an example of a client span:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// before you send a request, add metadata that describes the operation</span>
|
||||
span = tracer.newTrace().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"get"</span>).type(CLIENT);
|
||||
span.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"clnt/finagle.version"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"6.36.0"</span>);
|
||||
span.tag(TraceKeys.HTTP_PATH, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/api"</span>);
|
||||
span.remoteEndpoint(Endpoint.builder()
|
||||
.serviceName(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"backend"</span>)
|
||||
.ipv4(<span class="hl-number">127</span> << <span class="hl-number">24</span> | <span class="hl-number">1</span>)
|
||||
.port(<span class="hl-number">8080</span>).build());
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when the request is scheduled, start the span</span>
|
||||
span.start();
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// if you have callbacks for when data is on the wire, note those events</span>
|
||||
span.annotate(Constants.WIRE_SEND);
|
||||
span.annotate(Constants.WIRE_RECV);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when the response is complete, finish the span</span>
|
||||
span.finish();</pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_one_way_tracing" href="#_one_way_tracing"></a>One-Way tracing</h4></div></div></div><p>Sometimes you need to model an asynchronous operation, where there is a
|
||||
request, but no response. In normal RPC tracing, you use <code class="literal">span.finish()</code>
|
||||
which indicates the response was received. In one-way tracing, you use
|
||||
<code class="literal">span.flush()</code> instead, as you don’t expect a response.</p><p>Here’s how a client might model a one-way operation</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// start a new span representing a client request</span>
|
||||
oneWaySend = tracer.newSpan(parent).kind(Span.Kind.CLIENT);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Add the trace context to the request, so it can be propagated in-band</span>
|
||||
tracing.propagation().injector(Request::addHeader)
|
||||
.inject(oneWaySend.context(), request);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// fire off the request asynchronously, totally dropping any response</span>
|
||||
request.execute();
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// start the client side and flush instead of finish</span>
|
||||
oneWaySend.start().flush();</pre><p>And here’s how a server might handle this..</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// pull the context out of the incoming request</span>
|
||||
extractor = tracing.propagation().extractor(Request::getHeader);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// convert that context to a span which you can name and add tags to</span>
|
||||
oneWayReceive = nextSpan(tracer, extractor.extract(request))
|
||||
.name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"process-request"</span>)
|
||||
.kind(SERVER)
|
||||
... add tags etc.
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// start the server side and flush instead of finish</span>
|
||||
oneWayReceive.start().flush();
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// you should not modify this span anymore as it is complete. However,</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// you can create children to represent follow-up work.</span>
|
||||
next = tracer.newSpan(oneWayReceive.context()).name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"step2"</span>).start();</pre><p><span class="strong"><strong>Note</strong></span> The above propagation logic is a simplified version of our [http handlers](<a class="link" href="https://github.com/openzipkin/sleuth/tree/master/instrumentation/http#http-server" target="_top">https://github.com/openzipkin/sleuth/tree/master/instrumentation/http#http-server</a>).</p><p>There’s a working example of a one-way span [here](src/test/java/sleuth/features/async/OneWaySpanTest.java).</p></div></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__additional_resources.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__sampling.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. Additional resources </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"> 4. Sampling</td></tr></table></div></body></html>
|
||||
@@ -1,6 +1,6 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>5. Instrumentation</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__sampling.html" title="4. Sampling"><link rel="next" href="multi__span_lifecycle.html" title="6. Span lifecycle"></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">5. Instrumentation</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__sampling.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__span_lifecycle.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_instrumentation" href="#_instrumentation"></a>5. Instrumentation</h1></div></div></div><p>Spring Cloud Sleuth instruments all your Spring application
|
||||
<title>8. Instrumentation</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__current_span.html" title="7. Current Span"><link rel="next" href="multi__span_lifecycle.html" title="9. Span lifecycle"></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">8. Instrumentation</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__current_span.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__span_lifecycle.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_instrumentation" href="#_instrumentation"></a>8. Instrumentation</h1></div></div></div><p>Spring Cloud Sleuth instruments all your Spring application
|
||||
automatically, so you shouldn’t have to do anything to activate
|
||||
it. The instrumentation is added using a variety of technologies
|
||||
according to the stack that is available, e.g. for a servlet web
|
||||
@@ -12,7 +12,4 @@ request headers by configuring <code class="literal">spring.sleuth.keys.http.hea
|
||||
list of header names).</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Remember that tags are only collected and exported if there is a
|
||||
<code class="literal">Sampler</code> that allows it (by default there is not, so there is no
|
||||
danger of accidentally collecting too much data without configuring
|
||||
something).</p></td></tr></table></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>Currently the instrumentation in Spring Cloud Sleuth is eager - it means that
|
||||
we’re actively trying to pass the tracing context between threads. Also timing events
|
||||
are captured even when sleuth isn’t exporting data to a tracing system.
|
||||
This approach may change in the future towards being lazy on this matter.</p></td></tr></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__sampling.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__span_lifecycle.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4. Sampling </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"> 6. Span lifecycle</td></tr></table></div></body></html>
|
||||
something).</p></td></tr></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__current_span.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__span_lifecycle.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. Current Span </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"> 9. Span lifecycle</td></tr></table></div></body></html>
|
||||
@@ -1,6 +1,6 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>13. Integrations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__metrics.html" title="12. Metrics"><link rel="next" href="multi__running_examples.html" title="14. 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">13. Integrations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__metrics.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>13. Integrations</h1></div></div></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>13.1 Runnable and Callable</h2></div></div></div><p>If you’re wrapping your logic in <code class="literal">Runnable</code> or <code class="literal">Callable</code> it’s enough to wrap those classes in their Sleuth representative.</p><p>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() {
|
||||
<title>15. Integrations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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="_runnable_and_callable" href="#_runnable_and_callable"></a>15.1 Runnable and Callable</h2></div></div></div><p>If you’re wrapping your logic in <code class="literal">Runnable</code> or <code class="literal">Callable</code> it’s enough to wrap those classes in their Sleuth representative.</p><p>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() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<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>
|
||||
@@ -12,10 +12,11 @@
|
||||
}
|
||||
};
|
||||
<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(tracer, 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 `Tracer`. The Span name will be taken either from the</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// `@SpanName` annotation or from `toString` method</span>
|
||||
Runnable traceRunnableFromTracer = tracer.wrap(runnable);</pre><p>Example 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>() {
|
||||
Runnable traceRunnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceRunnable(tracer, spanNamer, errorParser,
|
||||
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 = tracing.currentTraceContext().wrap(runnable);</pre><p>Example 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>() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<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();
|
||||
@@ -27,13 +28,14 @@ Runnable traceRunnableFromTracer = tracer.wrap(runnable);</pre><p>Example for <c
|
||||
}
|
||||
};
|
||||
<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<>(tracer, 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 `Tracer`. The Span name will be taken either from the</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// `@SpanName` annotation or from `toString` method</span>
|
||||
Callable<String> traceCallableFromTracer = tracer.wrap(callable);</pre><p>That way you will 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>13.2 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>13.2.1 Custom Concurrency Strategy</h3></div></div></div><p>We’re registering a custom <a class="link" href="https://github.com/Netflix/Hystrix/wiki/Plugins#concurrencystrategy" target="_top"><code class="literal">HystrixConcurrencyStrategy</code></a>
|
||||
Callable<String> traceCallable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceCallable<>(tracer, spanNamer, errorParser,
|
||||
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 = tracing.currentTraceContext().wrap(callable);</pre><p>That way you will 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.2 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.2.1 Custom Concurrency Strategy</h3></div></div></div><p>We’re registering a custom <a class="link" href="https://github.com/Netflix/Hystrix/wiki/Plugins#concurrencystrategy" target="_top"><code class="literal">HystrixConcurrencyStrategy</code></a>
|
||||
that wraps all <code class="literal">Callable</code> instances into their Sleuth representative -
|
||||
the <code class="literal">TraceCallable</code>. The strategy either starts or continues a span depending on the fact whether tracing was already going
|
||||
on before the Hystrix command was called. To disable the custom Hystrix Concurrency Strategy set the <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>13.2.2 Manual Command setting</h3></div></div></div><p>Assuming 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) {
|
||||
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.2.2 Manual Command setting</h3></div></div></div><p>Assuming 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) {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em>
|
||||
<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();
|
||||
@@ -44,65 +46,36 @@ on before the Hystrix command was called. To disable the custom Hystrix Concurre
|
||||
<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>13.3 RxJava</h2></div></div></div><p>We’re registering a custom <a class="link" href="https://github.com/ReactiveX/RxJava/wiki/Plugins#rxjavaschedulershook" target="_top"><code class="literal">RxJavaSchedulersHook</code></a>
|
||||
};</pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_rxjava" href="#_rxjava"></a>15.3 RxJava</h2></div></div></div><p>We’re 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 into their Sleuth representative -
|
||||
the <code class="literal">TraceAction</code>. The hook either starts or continues a span depending on the fact whether tracing was already going
|
||||
on before the Action was scheduled. To disable the custom RxJavaSchedulersHook set the <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 don’t want a Span to be created. Just provide a comma separated list
|
||||
of regular expressions in the <code class="literal">spring.sleuth.rxjava.schedulers.ignoredthreads</code> property.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http_integration" href="#_http_integration"></a>13.4 HTTP integration</h2></div></div></div><p>Features from this section can be disabled by providing 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>13.4.1 HTTP Filter</h3></div></div></div><p>Via the <code class="literal">TraceFilter</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
|
||||
of regular expressions in the <code class="literal">spring.sleuth.rxjava.schedulers.ignoredthreads</code> property.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_http_integration" href="#_http_integration"></a>15.4 HTTP integration</h2></div></div></div><p>Features from this section can be disabled by providing 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.4.1 HTTP Filter</h3></div></div></div><p>Via the <code class="literal">TraceFilter</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. E.g. if the request was sent to <code class="literal">/foo/bar</code> then the name will be <code class="literal">http:/foo/bar</code>. You can configure which URIs you would
|
||||
like to skip via the <code class="literal">spring.sleuth.web.skipPattern</code> property. If you have <code class="literal">ManagementServerProperties</code> on classpath then
|
||||
its value of <code class="literal">contextPath</code> gets appended to the provided skip pattern.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_handlerinterceptor" href="#_handlerinterceptor"></a>13.4.2 HandlerInterceptor</h3></div></div></div><p>Since we want the span names to be precise we’re using a <code class="literal">TraceHandlerInterceptor</code> that either wraps an
|
||||
its value of <code class="literal">contextPath</code> gets appended to the provided skip pattern.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_handlerinterceptor" href="#_handlerinterceptor"></a>15.4.2 HandlerInterceptor</h3></div></div></div><p>Since we want the span names to be precise we’re using 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">TraceFilter</code> doesn’t see this attribute set it will create a "fallback" span which is an additional
|
||||
span created on the server side so that the trace is presented properly in the UI. Seeing that most likely
|
||||
signifies that there is a missing instrumentation. In that case please file an issue in Spring Cloud Sleuth.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_async_servlet_support" href="#_async_servlet_support"></a>13.4.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 will continue 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>13.4.4 WebFlux support</h3></div></div></div><p>Via the <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
|
||||
signifies that there is a 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.4.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 will continue 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.4.4 WebFlux support</h3></div></div></div><p>Via the <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. E.g. if the request was sent to <code class="literal">/foo/bar</code> then the name will be <code class="literal">http:/foo/bar</code>. You can configure which URIs you would
|
||||
like to skip via the <code class="literal">spring.sleuth.web.skipPattern</code> property. If you have <code class="literal">ManagementServerProperties</code> on classpath then
|
||||
its value of <code class="literal">contextPath</code> gets appended to the provided skip pattern.</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>13.5 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>13.5.1 Synchronous Rest Template</h3></div></div></div><p>We’re injecting a <code class="literal">RestTemplate</code> interceptor that ensures that all the tracing information is passed to the requests. Each time a
|
||||
its value of <code class="literal">contextPath</code> gets appended to the provided skip pattern.</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.5 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.5.1 Synchronous Rest Template</h3></div></div></div><p>We’re injecting a <code class="literal">RestTemplate</code> interceptor that ensures that all the tracing information is passed to the requests. Each time a
|
||||
call is made a new Span is created. It gets closed upon receiving the response. In order to block the synchronous <code class="literal">RestTemplate</code> features
|
||||
just 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 will get injected.
|
||||
If you create a <code class="literal">RestTemplate</code> instance with a <code class="literal">new</code> keyword then the instrumentation WILL 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>13.5.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>A traced version of an <code class="literal">AsyncRestTemplate</code> bean is registered for you out of the box. If you
|
||||
have your own bean you have to wrap it in a <code class="literal">TraceAsyncRestTemplate</code> representation. The best solution
|
||||
is to only customize the <code class="literal">ClientHttpRequestFactory</code> and / or <code class="literal">AsyncClientHttpRequestFactory</code>.
|
||||
<span class="strong"><strong>If you have your own <code class="literal">AsyncRestTemplate</code> and you don’t wrap it your calls WILL NOT GET TRACED</strong></span>.</p></td></tr></table></div><p>Custom instrumentation is set to create and close Spans upon sending and receiving requests. You can customize the <code class="literal">ClientHttpRequestFactory</code>
|
||||
and the <code class="literal">AsyncClientHttpRequestFactory</code> by registering your beans. Remember to use tracing compatible implementations (e.g. don’t forget to
|
||||
wrap <code class="literal">ThreadPoolTaskScheduler</code> in a <code class="literal">TraceAsyncListenableTaskExecutor</code>). Example of custom request factories:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> <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> TestConfiguration {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
ClientHttpRequestFactory mySyncClientFactory() {
|
||||
<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> MySyncClientHttpRequestFactory();
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
AsyncClientHttpRequestFactory myAsyncClientFactory() {
|
||||
<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> MyAsyncClientHttpRequestFactory();
|
||||
}
|
||||
}</pre><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>.
|
||||
If you create a <code class="literal">RestTemplate</code> instance with a <code class="literal">new</code> keyword then the instrumentation WILL 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.5.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’s up to you to create such
|
||||
a bean. Then we will 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 don’t 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 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"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
<em><span class="hl-annotation" style="color: gray">@EnableAutoConfiguration</span></em>
|
||||
<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 {
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> HttpTraceKeysInjector httpTraceKeysInjector;
|
||||
<em><span class="hl-annotation" style="color: gray">@Autowired</span></em> HttpSpanInjector spanInjector;
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean(name = "customAsyncRestTemplate")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> AsyncRestTemplate traceAsyncRestTemplate(<em><span class="hl-annotation" style="color: gray">@Qualifier("customHttpRequestFactoryWrapper")</span></em>
|
||||
TraceAsyncClientHttpRequestFactoryWrapper wrapper, ErrorParser errorParser) {
|
||||
<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> TraceAsyncRestTemplate(wrapper, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer, errorParser);
|
||||
}
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Bean(name = "customHttpRequestFactoryWrapper")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> TraceAsyncClientHttpRequestFactoryWrapper traceAsyncClientHttpRequestFactory() {
|
||||
<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> TraceAsyncClientHttpRequestFactoryWrapper(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.spanInjector,
|
||||
asyncClientFactory(),
|
||||
clientHttpRequestFactory(),
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.httpTraceKeysInjector);
|
||||
<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() {
|
||||
@@ -116,29 +89,29 @@ can see an example of how to set up such a custom <code class="literal">AsyncRes
|
||||
<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>13.5.3 WebClient</h3></div></div></div><p>We inject a <code class="literal">ExchangeFilterFunction</code> implementation that creates a span and via on success and on
|
||||
}</pre></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_webclient" href="#_webclient"></a>15.5.3 WebClient</h3></div></div></div><p>We inject a <code class="literal">ExchangeFilterFunction</code> implementation that creates a span and via on success and on
|
||||
error callbacks takes care of closing client side spans.</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 instrumention gets applied.
|
||||
If you create a <code class="literal">WebClient</code> instance with a <code class="literal">new</code> keyword then the instrumentation WILL 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>13.5.4 Traverson</h3></div></div></div><p>If you’re using the <a class="link" href="http://docs.spring.io/spring-hateoas/docs/current/reference/html/#client.traverson" target="_top">Traverson</a> library
|
||||
If you create a <code class="literal">WebClient</code> instance with a <code class="literal">new</code> keyword then the instrumentation WILL 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.5.4 Traverson</h3></div></div></div><p>If you’re using the <a class="link" href="http://docs.spring.io/spring-hateoas/docs/current/reference/html/#client.traverson" target="_top">Traverson</a> library
|
||||
it’s enough for you to inject a <code class="literal">RestTemplate</code> as a bean into your Traverson object. Since <code class="literal">RestTemplate</code>
|
||||
is already intercepted, you will get full support of tracing in your client. Below you can find a pseudo code
|
||||
of how to do that:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> 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><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_feign" href="#_feign"></a>13.6 Feign</h2></div></div></div><p>By default Spring Cloud Sleuth provides integration with feign via the <code class="literal">TraceFeignClientAutoConfiguration</code>. You can disable it entirely
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// use Traverson</span></pre></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_feign" href="#_feign"></a>15.6 Feign</h2></div></div></div><p>By default Spring Cloud Sleuth provides integration with feign via the <code class="literal">TraceFeignClientAutoConfiguration</code>. You can disable it entirely
|
||||
by setting <code class="literal">spring.sleuth.feign.enabled</code> to false. If you do so then no Feign related instrumentation will take place.</p><p>Part of Feign instrumentation is done via a <code class="literal">FeignBeanPostProcessor</code>. You can disable it by providing the <code class="literal">spring.sleuth.feign.processor.enabled</code> equal to <code class="literal">false</code>.
|
||||
If you set it like this then Spring Cloud Sleuth will not instrument any of your custom Feign components. All the default instrumentation
|
||||
however will be still there.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_asynchronous_communication" href="#_asynchronous_communication"></a>13.7 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>13.7.1 @Async annotated methods</h3></div></div></div><p>In Spring Cloud Sleuth we’re instrumenting async related components so that the tracing information is passed between threads.
|
||||
You can disable this behaviour by setting the value of <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> then we’ll 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> then the value of the annotation will be the Span’s name</li><li class="listitem">if the method is <span class="strong"><strong>not</strong></span> annotated with <code class="literal">@SpanName</code> the Span name will be the annotated method name</li><li class="listitem">the Span will be tagged with that method’s class name and the method name too</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>13.7.2 @Scheduled annotated methods</h3></div></div></div><p>In Spring Cloud Sleuth we’re instrumenting scheduled method execution so that the tracing information is passed between threads. You can disable this behaviour
|
||||
however will be still there.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_asynchronous_communication" href="#_asynchronous_communication"></a>15.7 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.7.1 @Async annotated methods</h3></div></div></div><p>In Spring Cloud Sleuth we’re instrumenting async related components so that the tracing information is passed between threads.
|
||||
You can disable this behaviour by setting the value of <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> then we’ll 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> then the value of the annotation will be the Span’s name</li><li class="listitem">if the method is <span class="strong"><strong>not</strong></span> annotated with <code class="literal">@SpanName</code> the Span name will be the annotated method name</li><li class="listitem">the Span will be tagged with that method’s class name and the method name too</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.7.2 @Scheduled annotated methods</h3></div></div></div><p>In Spring Cloud Sleuth we’re instrumenting scheduled method execution so that the tracing information is passed between threads. You can disable this behaviour
|
||||
by setting the value of <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> then we’ll 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 will be the annotated method name</li><li class="listitem">the Span will be tagged with that method’s class name and the method name too</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 will match the fully qualified name of the
|
||||
<code class="literal">@Scheduled</code> annotated class.</p><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>If you are using <code class="literal">spring-cloud-sleuth-stream</code> and <code class="literal">spring-cloud-netflix-hystrix-stream</code> together, Span will be created for each Hystrix metrics and sent to Zipkin. This may be annoying. You can prevent this by setting <code class="literal">spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask</code></p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_executor_executorservice_and_scheduledexecutorservice" href="#_executor_executorservice_and_scheduledexecutorservice"></a>13.7.3 Executor, ExecutorService and ScheduledExecutorService</h3></div></div></div><p>We’re providing <code class="literal">LazyTraceExecutor</code>, <code class="literal">TraceableExecutorService</code> and <code class="literal">TraceableScheduledExecutorService</code>. Those implementations
|
||||
<code class="literal">@Scheduled</code> annotated class.</p><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>If you are using <code class="literal">spring-cloud-sleuth-stream</code> and <code class="literal">spring-cloud-netflix-hystrix-stream</code> together, Span will be created for each Hystrix metrics and sent to Zipkin. This may be annoying. You can prevent this by setting <code class="literal">spring.sleuth.scheduled.skipPattern=org.springframework.cloud.netflix.hystrix.stream.HystrixStreamTask</code></p></td></tr></table></div></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.7.3 Executor, ExecutorService and ScheduledExecutorService</h3></div></div></div><p>We’re providing <code class="literal">LazyTraceExecutor</code>, <code class="literal">TraceableExecutorService</code> and <code class="literal">TraceableScheduledExecutorService</code>. Those implementations
|
||||
are creating Spans each time a new task is submitted, invoked or scheduled.</p><p>Here you can see an example of 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> <span class="hl-number">1</span>_<span class="hl-number">000</span>_<span class="hl-number">000L</span>;
|
||||
}, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceableExecutorService(executorService,
|
||||
}, <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>
|
||||
tracer, traceKeys, spanNamer, <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 doesn’t work with <code class="literal">parallelStream()</code> out of the box. If you want
|
||||
<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 doesn’t 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 presented above.</p></td></tr></table></div><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>. In the following snippet you
|
||||
can see an example of how to set up such a custom <code class="literal">Executor</code>.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Configuration</span></em>
|
||||
@@ -159,9 +132,9 @@ can see an example of how to set up such a custom <code class="literal">Executor
|
||||
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></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_messaging" href="#_messaging"></a>13.8 Messaging</h2></div></div></div><p>Spring Cloud Sleuth integrates with <a class="link" href="http://projects.spring.io/spring-integration/" target="_top">Spring Integration</a>. It creates spans for publish and
|
||||
}</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_messaging" href="#_messaging"></a>15.8 Messaging</h2></div></div></div><p>Spring Cloud Sleuth integrates with <a class="link" href="http://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 false.</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
|
||||
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> remember to use the <span class="strong"><strong>untraced</strong></span> version of the <code class="literal">Executor</code>.
|
||||
Decorating Spring Integration Executor Channel with <code class="literal">TraceableExecutorService</code> will cause the spans to be improperly closed.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_zuul" href="#_zuul"></a>13.9 Zuul</h2></div></div></div><p>We’re registering Zuul filters to propagate the tracing information (the request header is enriched with tracing data).
|
||||
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__metrics.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">12. Metrics </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"> 14. Running examples</td></tr></table></div></body></html>
|
||||
Decorating Spring Integration Executor Channel with <code class="literal">TraceableExecutorService</code> will cause the spans to be improperly closed.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_zuul" href="#_zuul"></a>15.9 Zuul</h2></div></div></div><p>We’re registering Zuul filters to propagate the tracing information (the request header is enriched with tracing data).
|
||||
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>
|
||||
@@ -6,28 +6,39 @@ is a part of. Spans also have other data, such as descriptions, timestamped eve
|
||||
annotations (tags), the ID of the span that caused them, and process ID’s (normally IP address).</p><p>Spans are 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.</p><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>The initial span that starts a trace is called a <code class="literal">root span</code>. The value of span id
|
||||
of that span is equal to trace id.</p></td></tr></table></div><p><span class="strong"><strong>Trace:</strong></span> A set of spans forming a tree-like structure. For example, if you are running a distributed
|
||||
big-data store, a trace might be formed by a put request.</p><p><span class="strong"><strong>Annotation:</strong></span> is used to record existence of an event in time. Some of the core annotations used to define
|
||||
the start and stop of a request are:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="strong"><strong>cs</strong></span> - Client Sent - The client has made a request. This annotation depicts the start of the span.</li><li class="listitem"><span class="strong"><strong>sr</strong></span> - Server Received - The server side got the request and will start processing it.
|
||||
big-data store, a trace might be formed by a put request.</p><p><span class="strong"><strong>Annotation:</strong></span> is used to record existence of an event in time. With
|
||||
<a class="link" href="https://github.com/openzipkin/brave" target="_top">Brave</a> instrumentation we no longer need to set special events
|
||||
for <a class="link" href="https://zipkin.io/" target="_top">Zipkin</a> to understand who the client and server are and where
|
||||
the request started and where it has ended. For learning purposes
|
||||
however we will mark these events to highlight what kind
|
||||
of an action took place.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="strong"><strong>cs</strong></span> - Client Sent - The client has made a request. This annotation depicts the start of the span.</li><li class="listitem"><span class="strong"><strong>sr</strong></span> - Server Received - The server side got the request and will start processing it.
|
||||
If one subtracts the cs timestamp from this timestamp one will receive the network latency.</li><li class="listitem"><span class="strong"><strong>ss</strong></span> - Server Sent - Annotated upon completion of request processing (when the response
|
||||
got sent back to the client). If one subtracts the sr timestamp from this timestamp one
|
||||
will receive the time needed by the server side to process the request.</li><li class="listitem"><span class="strong"><strong>cr</strong></span> - Client Received - Signifies the end of the span. The client has successfully received the
|
||||
response from the server side. If one subtracts the cs timestamp from this timestamp one
|
||||
will receive the whole time needed by the client to receive the response from the server.</li></ul></div><p>Visualization of what <span class="strong"><strong>Span</strong></span> and <span class="strong"><strong>Trace</strong></span> will look in a system together with the Zipkin annotations:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/trace-id.png" alt="Trace Info propagation"></div></div><p>Each color of a note signifies a span (7 spans - from <span class="strong"><strong>A</strong></span> to <span class="strong"><strong>G</strong></span>). If you have such information in the note:</p><pre class="screen">Trace Id = X
|
||||
Span Id = D
|
||||
Client Sent</pre><p>That means that the current span has <span class="strong"><strong>Trace-Id</strong></span> set to <span class="strong"><strong>X</strong></span>, <span class="strong"><strong>Span-Id</strong></span> set to <span class="strong"><strong>D</strong></span>. It also has emitted
|
||||
<span class="strong"><strong>Client Sent</strong></span> event.</p><p>This is how the visualization of the parent / child relationship of spans would look like:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/parents.png" alt="Parent child relationship"></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_purpose" href="#_purpose"></a>1.2 Purpose</h2></div></div></div><p>In the following sections the example from the image above will be taken into consideration.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_distributed_tracing_with_zipkin" href="#_distributed_tracing_with_zipkin"></a>1.2.1 Distributed tracing with Zipkin</h3></div></div></div><p>Altogether there are <span class="strong"><strong>7 spans</strong></span> . If you go to traces in Zipkin you will see this number in the second trace:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-traces.png" alt="Traces"></div></div><p>However if you pick a particular trace then you will see <span class="strong"><strong>4 spans</strong></span>:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-ui.png" alt="Traces Info propagation"></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>When picking a particular trace you will see merged spans. That means that if there were 2 spans sent to
|
||||
Client Sent</pre><p>That means that the current span has <span class="strong"><strong>Trace-Id</strong></span> set to <span class="strong"><strong>X</strong></span>, <span class="strong"><strong>Span-Id</strong></span> set to <span class="strong"><strong>D</strong></span>. Also, the
|
||||
<span class="strong"><strong>Client Sent</strong></span> event took place.</p><p>This is how the visualization of the parent / child relationship of spans would look like:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/parents.png" alt="Parent child relationship"></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_purpose" href="#_purpose"></a>1.2 Purpose</h2></div></div></div><p>In the following sections the example from the image above will be taken into consideration.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_distributed_tracing_with_zipkin" href="#_distributed_tracing_with_zipkin"></a>1.2.1 Distributed tracing with Zipkin</h3></div></div></div><p>Altogether there are <span class="strong"><strong>7 spans</strong></span> . If you go to traces in Zipkin you will see this number in the second trace:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-traces.png" alt="Traces"></div></div><p>However if you pick a particular trace then you will see <span class="strong"><strong>4 spans</strong></span>:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-ui.png" alt="Traces Info propagation"></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>When picking a particular trace you will see merged spans. That means that if there were 2 spans sent to
|
||||
Zipkin with Server Received and Server Sent / Client Received and Client Sent
|
||||
annotations then they will presented as a single span.</p></td></tr></table></div><p>Why is there a difference between the 7 and 4 spans in this case?</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">2 spans come from <code class="literal">http:/start</code> span. It has the Server Received (SR) and Server Sent (SS) annotations.</li><li class="listitem">2 spans come from the RPC call from <code class="literal">service1</code> to <code class="literal">service2</code> to the <code class="literal">http:/foo</code> endpoint. It has the Client Sent (CS)
|
||||
and Client Received (CR) annotations on <code class="literal">service1</code> side. It also has Server Received (SR) and Server Sent (SS) annotations
|
||||
on the <code class="literal">service2</code> side. Physically there are 2 spans but they form 1 logical span related to an RPC call.</li><li class="listitem">2 spans come from the RPC call from <code class="literal">service2</code> to <code class="literal">service3</code> to the <code class="literal">http:/bar</code> endpoint. It has the Client Sent (CS)
|
||||
and Client Received (CR) annotations on <code class="literal">service2</code> side. It also has Server Received (SR) and Server Sent (SS) annotations
|
||||
on the <code class="literal">service3</code> side. Physically there are 2 spans but they form 1 logical span related to an RPC call.</li><li class="listitem">2 spans come from the RPC call from <code class="literal">service2</code> to <code class="literal">service4</code> to the <code class="literal">http:/baz</code> endpoint. It has the Client Sent (CS)
|
||||
and Client Received (CR) annotations on <code class="literal">service2</code> side. It also has Server Received (SR) and Server Sent (SS) annotations
|
||||
annotations then they will presented as a single span.</p></td></tr></table></div><p>Why is there a difference between the 7 and 4 spans in this case?</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">2 spans come from <code class="literal">http:/start</code> span. It has the Server Received (SR) and Server Sent (SS) annotations.</li><li class="listitem">2 spans come from the RPC call from <code class="literal">service1</code> to <code class="literal">service2</code> to the <code class="literal">http:/foo</code> endpoint. The Client Sent (CS)
|
||||
and Client Received (CR) events took place on <code class="literal">service1</code> side. Server Received (SR) and Server Sent (SS) events took place
|
||||
on the <code class="literal">service2</code> side. Physically there are 2 spans but they form 1 logical span related to an RPC call.</li><li class="listitem">2 spans come from the RPC call from <code class="literal">service2</code> to <code class="literal">service3</code> to the <code class="literal">http:/bar</code> endpoint. The Client Sent (CS)
|
||||
and Client Received (CR) events took place on <code class="literal">service2</code> side. Server Received (SR) and Server Sent (SS) events took place
|
||||
on the <code class="literal">service3</code> side. Physically there are 2 spans but they form 1 logical span related to an RPC call.</li><li class="listitem">2 spans come from the RPC call from <code class="literal">service2</code> to <code class="literal">service4</code> to the <code class="literal">http:/baz</code> endpoint. The Client Sent (CS)
|
||||
and Client Received (CR) events took place on <code class="literal">service2</code> side. Server Received (SR) and Server Sent (SS) events took place
|
||||
on the <code class="literal">service4</code> side. Physically there are 2 spans but they form 1 logical span related to an RPC call.</li></ul></div><p>So if we count the physical spans we have <span class="strong"><strong>1</strong></span> from <code class="literal">http:/start</code>, <span class="strong"><strong>2</strong></span> from <code class="literal">service1</code> calling <code class="literal">service2</code>, <span class="strong"><strong>2</strong></span> form <code class="literal">service2</code>
|
||||
calling <code class="literal">service3</code> and <span class="strong"><strong>2</strong></span> from <code class="literal">service2</code> calling <code class="literal">service4</code>. Altogether <span class="strong"><strong>7</strong></span> spans.</p><p>Logically we see the information of <span class="strong"><strong>Total Spans: 4</strong></span> because we have <span class="strong"><strong>1</strong></span> span related to the incoming request
|
||||
to <code class="literal">service1</code> and <span class="strong"><strong>3</strong></span> spans related to RPC calls.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_visualizing_errors" href="#_visualizing_errors"></a>1.2.2 Visualizing errors</h3></div></div></div><p>Zipkin allows you to visualize errors in your trace. When an exception was thrown and wasn’t caught then we’re
|
||||
setting proper tags on the span which Zipkin can properly colorize. You could see in the list of traces one
|
||||
trace that was in red color. That’s because there was an exception thrown.</p><p>If you click that trace then you’ll see a similar picture</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-error-traces.png" alt="Error Traces"></div></div><p>Then if you click on one of the spans you’ll see the following</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-error-trace-screenshot.png" alt="Error Traces Info propagation"></div></div><p>As you can see you can easily see the reason for an error and the whole stacktrace related to it.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_live_examples" href="#_live_examples"></a>1.2.3 Live examples</h3></div></div></div><div class="figure"><a name="d0e308" href="#d0e308"></a><p class="title"><b>Figure 1.1. Click Pivotal Web Services icon to see it live!</b></p><div class="figure-contents"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/pws.png" alt="Zipkin deployed on Pivotal Web Services"></div></div></div><br class="figure-break"><p>The dependency graph in Zipkin would look like this:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/dependencies.png" alt="Dependencies"></div></div><div class="figure"><a name="d0e326" href="#d0e326"></a><p class="title"><b>Figure 1.2. Click Pivotal Web Services icon to see it live!</b></p><div class="figure-contents"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/pws.png" alt="Zipkin deployed on Pivotal Web Services"></div></div></div><br class="figure-break"></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_log_correlation" href="#_log_correlation"></a>1.2.4 Log correlation</h3></div></div></div><p>When grepping the logs of those four applications by trace id equal to e.g. <code class="literal">2485ec27856c56f4</code> one would get the following:</p><pre class="screen">service1.log:2016-02-26 11:15:47.561 INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application : Hello from service1. Calling service2
|
||||
trace that was in red color. That’s because there was an exception thrown.</p><p>If you click that trace then you’ll see a similar picture</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-error-traces.png" alt="Error Traces"></div></div><p>Then if you click on one of the spans you’ll see the following</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/zipkin-error-trace-screenshot.png" alt="Error Traces Info propagation"></div></div><p>As you can see you can easily see the reason for an error and the whole stacktrace related to it.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_distributed_tracing_with_brave" href="#_distributed_tracing_with_brave"></a>1.2.3 Distributed tracing with Brave</h3></div></div></div><p>Starting with version <code class="literal">2.0.0</code>, Spring Cloud Sleuth uses
|
||||
<a class="link" href="https://github.com/openzipkin/brave" target="_top">Brave</a> as the tracing library. That means
|
||||
that Sleuth no longer takes care of storing the context but it delegates
|
||||
that work to Brave.</p><p>Due to the fact that Sleuth had different naming / tagging
|
||||
conventions than Brave, we’ve decided to follow the Brave’s
|
||||
conventions from now on. However, if you want to use the legacy
|
||||
Sleuth approaches, it’s enough to set the <code class="literal">spring.sleuth.http.legacy.enabled</code> property
|
||||
to <code class="literal">true</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_live_examples" href="#_live_examples"></a>1.2.4 Live examples</h3></div></div></div><div class="figure"><a name="d0e333" href="#d0e333"></a><p class="title"><b>Figure 1.1. Click Pivotal Web Services icon to see it live!</b></p><div class="figure-contents"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/pws.png" alt="Zipkin deployed on Pivotal Web Services"></div></div></div><br class="figure-break"><p><a class="link" href="http://docssleuth-zipkin-server.cfapps.io/" target="_top">Click here to see it live!</a></p><p>The dependency graph in Zipkin would look like this:</p><div class="informalfigure"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/dependencies.png" alt="Dependencies"></div></div><div class="figure"><a name="d0e354" href="#d0e354"></a><p class="title"><b>Figure 1.2. Click Pivotal Web Services icon to see it live!</b></p><div class="figure-contents"><div class="mediaobject"><img src="https://raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/docs/src/main/asciidoc/images/pws.png" alt="Zipkin deployed on Pivotal Web Services"></div></div></div><br class="figure-break"><p><a class="link" href="http://docssleuth-zipkin-server.cfapps.io/dependency" target="_top">Click here to see it live!</a></p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_log_correlation" href="#_log_correlation"></a>1.2.5 Log correlation</h3></div></div></div><p>When grepping the logs of those four applications by trace id equal to e.g. <code class="literal">2485ec27856c56f4</code> one would get the following:</p><pre class="screen">service1.log:2016-02-26 11:15:47.561 INFO [service1,2485ec27856c56f4,2485ec27856c56f4,true] 68058 --- [nio-8081-exec-1] i.s.c.sleuth.docs.service1.Application : Hello from service1. Calling service2
|
||||
service2.log:2016-02-26 11:15:47.710 INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application : Hello from service2. Calling service3 and then service4
|
||||
service3.log:2016-02-26 11:15:47.895 INFO [service3,2485ec27856c56f4,1210be13194bfe5,true] 68060 --- [nio-8083-exec-1] i.s.c.sleuth.docs.service3.Application : Hello from service3
|
||||
service2.log:2016-02-26 11:15:47.924 INFO [service2,2485ec27856c56f4,9aa10ee6fbde75fa,true] 68059 --- [nio-8082-exec-1] i.s.c.sleuth.docs.service2.Application : Got response from service3 [Hello from service3]
|
||||
@@ -122,41 +133,34 @@ we’re passing the dependencies in the <code class="literal">groupId:artifa
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment"><!--<appender-ref ref="flatfile"/>--></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></root></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></configuration></span></pre><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>If you’re using a custom <code class="literal">logback-spring.xml</code> then you have to pass the <code class="literal">spring.application.name</code> in
|
||||
<code class="literal">bootstrap</code> instead of <code class="literal">application</code> property file. Otherwise your custom logback file won’t read the property properly.</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_propagating_span_context" href="#_propagating_span_context"></a>1.2.5 Propagating Span Context</h3></div></div></div><p>The span context is the state that must get propagated to any child Spans across process boundaries.
|
||||
<code class="literal">bootstrap</code> instead of <code class="literal">application</code> property file. Otherwise your custom logback file won’t read the property properly.</p></td></tr></table></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_propagating_span_context" href="#_propagating_span_context"></a>1.2.6 Propagating Span Context</h3></div></div></div><p>The span context is the state that must get propagated to any child Spans across process boundaries.
|
||||
Part of the Span Context is the Baggage. The trace and span IDs are a required part of the span context.
|
||||
Baggage is an optional part.</p><p>Baggage is a set of key:value pairs stored in the span context. Baggage travels together with the trace
|
||||
and is attached to every span. Spring Cloud Sleuth will understand that a header is baggage related if the HTTP
|
||||
header is prefixed with <code class="literal">baggage-</code> and for messaging it starts with <code class="literal">baggage_</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>There’s currently no limitation of the count or size of baggage items. However, keep in mind that
|
||||
too many can decrease system throughput or increase RPC latency. In extreme cases, it could crash the app due
|
||||
to exceeding transport-level message or header capacity.</p></td></tr></table></div><p>Example of setting baggage on a span:</p><pre class="programlisting">Span initialSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.createSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"span"</span>);
|
||||
initialSpan.setBaggageItem(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"bar"</span>);
|
||||
initialSpan.setBaggageItem(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"UPPER_CASE"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"someValue"</span>);</pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_baggage_vs_span_tags" href="#_baggage_vs_span_tags"></a>Baggage vs. Span Tags</h4></div></div></div><p>Baggage travels with the trace (i.e. every child span contains the baggage of its parent). Zipkin has no knowledge of
|
||||
to exceeding transport-level message or header capacity.</p></td></tr></table></div><p>Example of setting baggage on a span:</p><pre class="programlisting">Unresolved directive in intro.adoc - include::https:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/brave/instrument/web/multiple/MultipleHopsIntegrationTests.java[tags=baggage,indent=0]</span>
|
||||
}</pre><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_baggage_vs_span_tags" href="#_baggage_vs_span_tags"></a>Baggage vs. Span Tags</h4></div></div></div><p>Baggage travels with the trace (i.e. every child span contains the baggage of its parent). Zipkin has no knowledge of
|
||||
baggage and will not even receive that information.</p><p>Tags are attached to a specific span - they are presented for that particular span only. However you
|
||||
can search by tag to find the trace, where there exists a span having the searched tag value.</p><p>If you want to be able to lookup a span based on baggage, you should add corresponding entry as a tag in the root span.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Autowired</span></em> Tracer tracer;
|
||||
|
||||
Span span = tracer.getCurrentSpan();
|
||||
String baggageKey = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"key"</span>;
|
||||
String baggageValue = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"foo"</span>;
|
||||
span.setBaggageItem(baggageKey, baggageValue);
|
||||
tracer.addTag(baggageKey, baggageValue);</pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_adding_to_the_project" href="#_adding_to_the_project"></a>1.3 Adding to the project</h2></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>To ensure that your application name is properly displayed in Zipkin
|
||||
can search by tag to find the trace, where there exists a span having the searched tag value.</p><p>If you want to be able to lookup a span based on baggage, you should add corresponding entry as a tag in the root span.</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>Remember that the span needs to be in scope!</p></td></tr></table></div><pre class="programlisting">Unresolved directive in intro.adoc - include::https:<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">//raw.githubusercontent.com/spring-cloud/spring-cloud-sleuth/master/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/brave/instrument/web/multiple/MultipleHopsIntegrationTests.java[tags=baggage_tag,indent=0]</span></pre></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_adding_to_the_project" href="#_adding_to_the_project"></a>1.3 Adding to the project</h2></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>To ensure that your application name is properly displayed in Zipkin
|
||||
set the <code class="literal">spring.application.name</code> property in <code class="literal">bootstrap.yml</code>.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_only_sleuth_log_correlation" href="#_only_sleuth_log_correlation"></a>1.3.1 Only Sleuth (log correlation)</h3></div></div></div><p>If you want to profit only from Spring Cloud Sleuth without the Zipkin integration just add
|
||||
the <code class="literal">spring-cloud-starter-sleuth</code> module to your project.</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span> <a name="CO1-1" href="#CO1-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<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>org.springframework.cloud<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>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<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>org.springframework.cloud<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>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO1-2" href="#CO1-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<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>spring-cloud-starter-sleuth<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 class="primary">
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO1-2" href="#CO1-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<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>spring-cloud-starter-sleuth<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 class="primary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO1-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO1-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-sleuth</code></p></td></tr></table></div><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">dependencyManagement { <a name="CO2-1" href="#CO2-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
@@ -171,21 +175,21 @@ dependencies { <a name="CO2-2" href="#CO2-2"></a><span><img src="images/callouts
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO2-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO2-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-sleuth</code></p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_sleuth_with_zipkin_via_http" href="#_sleuth_with_zipkin_via_http"></a>1.3.2 Sleuth with Zipkin via HTTP</h3></div></div></div><p>If you want both Sleuth and Zipkin just add the <code class="literal">spring-cloud-starter-zipkin</code> dependency.</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span> <a name="CO3-1" href="#CO3-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<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>org.springframework.cloud<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>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<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>org.springframework.cloud<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>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO3-2" href="#CO3-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<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>spring-cloud-starter-zipkin<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 class="primary">
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO3-2" href="#CO3-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<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>spring-cloud-starter-zipkin<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 class="primary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO3-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO3-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-zipkin</code></p></td></tr></table></div><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">dependencyManagement { <a name="CO4-1" href="#CO4-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
@@ -202,25 +206,25 @@ the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a h
|
||||
dependencies. The default destination name is <code class="literal">zipkin</code>.</p><p><span class="emphasis"><em>Note: <code class="literal">spring-cloud-sleuth-stream</code> is deprecated and incompatible with these destinations</em></span></p><p>If you want Sleuth over RabbitMQ add the <code class="literal">spring-cloud-starter-zipkin</code> and <code class="literal">spring-rabbit</code>
|
||||
dependencies.</p><p class="primary"><b>Maven. </b>
|
||||
</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencyManagement></span> <a name="CO5-1" href="#CO5-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<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>org.springframework.cloud<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>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependencies></span>
|
||||
<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>org.springframework.cloud<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>spring-cloud-dependencies<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></artifactId></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><version></span>${release.train.version}<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></version></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><type></span>pom<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></type></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><scope></span>import<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></scope></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependency></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencies></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"></dependencyManagement></span>
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO5-2" href="#CO5-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<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>spring-cloud-starter-zipkin<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>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO5-3" href="#CO5-3"></a><span><img src="images/callouts/3.png" alt="3" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.amqp<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>spring-rabbit<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 class="primary">
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO5-2" href="#CO5-2"></a><span><img src="images/callouts/2.png" alt="2" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.cloud<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>spring-cloud-starter-zipkin<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>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><dependency></span> <a name="CO5-3" href="#CO5-3"></a><span><img src="images/callouts/3.png" alt="3" border="0"></span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-tag"><groupId></span>org.springframework.amqp<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>spring-rabbit<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 class="primary">
|
||||
</p><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><p><a href="#CO5-1"><span><img src="images/callouts/1.png" alt="1" border="0"></span></a> </p></td><td valign="top" align="left"><p>In order not to pick versions by yourself it’s much better if you add the dependency management via
|
||||
the Spring BOM</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO5-2"><span><img src="images/callouts/2.png" alt="2" border="0"></span></a> </p></td><td valign="top" align="left"><p>Add the dependency to <code class="literal">spring-cloud-starter-zipkin</code> - that way all dependent dependencies will be downloaded</p></td></tr><tr><td width="5%" valign="top" align="left"><p><a href="#CO5-3"><span><img src="images/callouts/3.png" alt="3" border="0"></span></a> </p></td><td valign="top" align="left"><p>To automatically configure rabbit, simply add the spring-rabbit dependency</p></td></tr></table></div><p class="secondary"><b>Gradle. </b>
|
||||
</p><pre class="programlisting">dependencyManagement { <a name="CO6-1" href="#CO6-1"></a><span><img src="images/callouts/1.png" alt="1" border="0"></span>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>8. Managing spans with annotations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__naming_spans.html" title="7. Naming spans"><link rel="next" href="multi__customizations.html" title="9. Customizations"></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">8. Managing spans with annotations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__naming_spans.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__customizations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_managing_spans_with_annotations" href="#_managing_spans_with_annotations"></a>8. Managing spans with annotations</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_rationale" href="#_rationale"></a>8.1 Rationale</h2></div></div></div><p>The main arguments for this features are</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">api-agnostic means to collaborate with a span</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">use of annotations allows users to add to a span with no library dependency on a span api.
|
||||
<title>11. Managing spans with annotations</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__naming_spans.html" title="10. Naming spans"><link rel="next" href="multi__customizations.html" title="12. Customizations"></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">11. Managing spans with annotations</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__naming_spans.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__customizations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_managing_spans_with_annotations" href="#_managing_spans_with_annotations"></a>11. Managing spans with annotations</h1></div></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_rationale" href="#_rationale"></a>11.1 Rationale</h2></div></div></div><p>The main arguments for this features are</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p class="simpara">api-agnostic means to collaborate with a span</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">use of annotations allows users to add to a span with no library dependency on a span api.
|
||||
This allows Sleuth to change its core api less impact to user code.</li></ul></div></li><li class="listitem"><p class="simpara">reduced surface area for basic span operations.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">without this feature one has to use the span api, which has lifecycle commands that
|
||||
could be used incorrectly. By only exposing scope, tag and log functionality, users can
|
||||
collaborate without accidentally breaking span lifecycle.</li></ul></div></li><li class="listitem"><p class="simpara">collaboration with runtime generated code</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "><li class="listitem">with libraries such as Spring Data / Feign the implementations of interfaces are generated
|
||||
at runtime thus span wrapping of objects was tedious. Now you can provide annotations
|
||||
over interfaces and arguments of those interfaces</li></ul></div></li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_creating_new_spans" href="#_creating_new_spans"></a>8.2 Creating new spans</h2></div></div></div><p>If you really don’t want to take care of creating local spans manually you can profit from the
|
||||
over interfaces and arguments of those interfaces</li></ul></div></li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_creating_new_spans" href="#_creating_new_spans"></a>11.2 Creating new spans</h2></div></div></div><p>If you really don’t want to take care of creating local spans manually you can profit from the
|
||||
<code class="literal">@NewSpan</code> annotation. Also we give you the <code class="literal">@SpanTag</code> annotation to add tags in an automated
|
||||
fashion.</p><p>Let’s look at some examples of usage.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> testMethod();</pre><p>Annotating the method without any parameter will lead to a creation of a new span whose name
|
||||
@@ -23,25 +23,26 @@ the tag key will be <code class="literal">testTag</code> and the tag value will
|
||||
<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> testMethod3() {
|
||||
}</pre><p>You can place the <code class="literal">@NewSpan</code> annotation on both the class and an interface. If you override the
|
||||
interface’s method and provide a different value of the <code class="literal">@NewSpan</code> annotation then the most
|
||||
concrete one wins (in this case <code class="literal">customNameOnTestMethod3</code> will be set).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_continuing_spans" href="#_continuing_spans"></a>8.3 Continuing spans</h2></div></div></div><p>If you want to just add tags and annotations to an existing span it’s enough
|
||||
concrete one wins (in this case <code class="literal">customNameOnTestMethod3</code> will be set).</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_continuing_spans" href="#_continuing_spans"></a>11.3 Continuing spans</h2></div></div></div><p>If you want to just add tags and annotations to an existing span it’s enough
|
||||
to use the <code class="literal">@ContinueSpan</code> annotation as presented below. Note that in contrast
|
||||
with the <code class="literal">@NewSpan</code> annotation you can also add logs via the <code class="literal">log</code> parameter:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// method declaration</span>
|
||||
<em><span class="hl-annotation" style="color: gray">@ContinueSpan(log = "testMethod11")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">void</span> testMethod11(<em><span class="hl-annotation" style="color: gray">@SpanTag("testTag11")</span></em> String param);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// method execution</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.testBean.testMethod11(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"test"</span>);</pre><p>That way the span will get continued and:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">logs with name <code class="literal">testMethod11.before</code> and <code class="literal">testMethod11.after</code> will be created</li><li class="listitem">if an exception will be thrown a log <code class="literal">testMethod11.afterFailure</code> will also be created</li><li class="listitem">tag with key <code class="literal">testTag11</code> and value <code class="literal">test</code> will be created</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_more_advanced_tag_setting" href="#_more_advanced_tag_setting"></a>8.4 More advanced tag setting</h2></div></div></div><p>There are 3 different ways to add tags to a span. All of them are controlled by the <code class="literal">SpanTag</code> annotation.
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.testBean.testMethod11(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"test"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.testBean.testMethod13();</pre><p>That way the span will get continued and:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">logs with name <code class="literal">testMethod11.before</code> and <code class="literal">testMethod11.after</code> will be created</li><li class="listitem">if an exception will be thrown a log <code class="literal">testMethod11.afterFailure</code> will also be created</li><li class="listitem">tag with key <code class="literal">testTag11</code> and value <code class="literal">test</code> will be created</li></ul></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_more_advanced_tag_setting" href="#_more_advanced_tag_setting"></a>11.4 More advanced tag setting</h2></div></div></div><p>There are 3 different ways to add tags to a span. All of them are controlled by the <code class="literal">SpanTag</code> annotation.
|
||||
Precedence is:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">try with the bean of <code class="literal">TagValueResolver</code> type and provided name</li><li class="listitem">if one hasn’t provided the bean name, try to evaluate an expression. We’re searching for a <code class="literal">TagValueExpressionResolver</code> bean.
|
||||
The default implementation uses SPEL expression resolution.</li><li class="listitem">if one hasn’t provided any expression to evaluate just return a <code class="literal">toString()</code> value of the parameter</li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_custom_extractor" href="#_custom_extractor"></a>8.4.1 Custom extractor</h3></div></div></div><p>The value of the tag for following method will be computed by an implementation of <code class="literal">TagValueResolver</code> interface.
|
||||
The default implementation uses SPEL expression resolution.</li><li class="listitem">if one hasn’t provided any expression to evaluate just return a <code class="literal">toString()</code> value of the parameter</li></ul></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_custom_extractor" href="#_custom_extractor"></a>11.4.1 Custom extractor</h3></div></div></div><p>The value of the tag for following method will be computed by an implementation of <code class="literal">TagValueResolver</code> interface.
|
||||
Its class name has to be passed as the value of the <code class="literal">resolver</code> attribute.</p><p>Having such an annotated method:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</span></em>
|
||||
<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> getAnnotationForTagValueResolver(<em><span class="hl-annotation" style="color: gray">@SpanTag(key = "test", resolver = TagValueResolver.class)</span></em> String test) {
|
||||
}</pre><p>and such a <code class="literal">TagValueResolver</code> bean implementation</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean(name = "myCustomTagValueResolver")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> TagValueResolver tagValueResolver() {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> parameter -> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"Value from myCustomTagValueResolver"</span>;
|
||||
}</pre><p>Will lead to setting of a tag value equal to <code class="literal">Value from myCustomTagValueResolver</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_resolving_expressions_for_value" href="#_resolving_expressions_for_value"></a>8.4.2 Resolving expressions for value</h3></div></div></div><p>Having such an annotated method:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</span></em>
|
||||
}</pre><p>Will lead to setting of a tag value equal to <code class="literal">Value from myCustomTagValueResolver</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_resolving_expressions_for_value" href="#_resolving_expressions_for_value"></a>11.4.2 Resolving expressions for value</h3></div></div></div><p>Having such an annotated method:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</span></em>
|
||||
<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> getAnnotationForTagValueExpression(<em><span class="hl-annotation" style="color: gray">@SpanTag(key = "test", expression = "length() + ' characters'")</span></em> String test) {
|
||||
}</pre><p>and no custom implementation of a <code class="literal">TagValueExpressionResolver</code> will lead to evaluation of the SPEL expression and a tag with value <code class="literal">4 characters</code> will be set on the span.
|
||||
If you want to use some other expression resolution mechanism you can create your own implementation
|
||||
of the bean.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_tostring_method" href="#_using_tostring_method"></a>8.4.3 Using toString method</h3></div></div></div><p>Having such an annotated method:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</span></em>
|
||||
of the bean.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_using_tostring_method" href="#_using_tostring_method"></a>11.4.3 Using toString method</h3></div></div></div><p>Having such an annotated method:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@NewSpan</span></em>
|
||||
<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> getAnnotationForArgumentToString(<em><span class="hl-annotation" style="color: gray">@SpanTag("test")</span></em> Long param) {
|
||||
}</pre><p>if executed with a value of <code class="literal">15</code> will lead to setting of a tag with a String value of <code class="literal">"15"</code>.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__naming_spans.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__customizations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. Naming spans </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"> 9. Customizations</td></tr></table></div></body></html>
|
||||
}</pre><p>if executed with a value of <code class="literal">15</code> will lead to setting of a tag with a String value of <code class="literal">"15"</code>.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__naming_spans.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__customizations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">10. Naming spans </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"> 12. Customizations</td></tr></table></div></body></html>
|
||||
@@ -1,19 +1,20 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>7. Naming spans</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__span_lifecycle.html" title="6. Span lifecycle"><link rel="next" href="multi__managing_spans_with_annotations.html" title="8. Managing spans with annotations"></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">7. Naming spans</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__span_lifecycle.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__managing_spans_with_annotations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_naming_spans" href="#_naming_spans"></a>7. Naming spans</h1></div></div></div><p>Picking a span name is not a trivial task. Span name should depict an operation name. The name should
|
||||
<title>10. Naming spans</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__span_lifecycle.html" title="9. Span lifecycle"><link rel="next" href="multi__managing_spans_with_annotations.html" title="11. Managing spans with annotations"></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">10. Naming spans</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__span_lifecycle.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__managing_spans_with_annotations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_naming_spans" href="#_naming_spans"></a>10. Naming spans</h1></div></div></div><p>Picking a span name is not a trivial task. Span name should depict an operation name. The name should
|
||||
be low cardinality (e.g. not include identifiers).</p><p>Since there is a lot of instrumentation going on some of the span names will be
|
||||
artificial like:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">controller-method-name</code> when received by a Controller with a method name <code class="literal">conrollerMethodName</code></li><li class="listitem"><code class="literal">async</code> for asynchronous operations done via wrapped <code class="literal">Callable</code> and <code class="literal">Runnable</code>.</li><li class="listitem"><code class="literal">@Scheduled</code> annotated methods will return the simple name of the class.</li></ul></div><p>Fortunately, for the asynchronous processing you can provide explicit naming.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="__spanname_annotation" href="#__spanname_annotation"></a>7.1 @SpanName annotation</h2></div></div></div><p>You can name the span explicitly via the <code class="literal">@SpanName</code> annotation.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpanName("calculateTax")</span></em>
|
||||
artificial like:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><code class="literal">controller-method-name</code> when received by a Controller with a method name <code class="literal">conrollerMethodName</code></li><li class="listitem"><code class="literal">async</code> for asynchronous operations done via wrapped <code class="literal">Callable</code> and <code class="literal">Runnable</code>.</li><li class="listitem"><code class="literal">@Scheduled</code> annotated methods will return the simple name of the class.</li></ul></div><p>Fortunately, for the asynchronous processing you can provide explicit naming.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="__spanname_annotation" href="#__spanname_annotation"></a>10.1 @SpanName annotation</h2></div></div></div><p>You can name the span explicitly via the <code class="literal">@SpanName</code> annotation.</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@SpanName("calculateTax")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">class</span> TaxCountingRunnable <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">implements</span> Runnable {
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <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">// perform logic</span>
|
||||
}
|
||||
}</pre><p>In this case, when processed in the following manner:</p><pre class="programlisting">Runnable runnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceRunnable(tracer, spanNamer, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TaxCountingRunnable());
|
||||
}</pre><p>In this case, when processed in the following manner:</p><pre class="programlisting">Runnable runnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceRunnable(tracer, spanNamer, errorParser,
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TaxCountingRunnable());
|
||||
Future<?> future = executorService.submit(runnable);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ... some additional logic ...</span>
|
||||
future.get();</pre><p>The span will be named <code class="literal">calculateTax</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_tostring_method" href="#_tostring_method"></a>7.2 toString() method</h2></div></div></div><p>It’s pretty rare to create separate classes for <code class="literal">Runnable</code> or <code class="literal">Callable</code>. Typically one creates an anonymous
|
||||
future.get();</pre><p>The span will be named <code class="literal">calculateTax</code>.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_tostring_method" href="#_tostring_method"></a>10.2 toString() method</h2></div></div></div><p>It’s pretty rare to create separate classes for <code class="literal">Runnable</code> or <code class="literal">Callable</code>. Typically one creates an anonymous
|
||||
instance of those classes. You can’t annotate such classes thus to override that, if there is no <code class="literal">@SpanName</code> annotation present,
|
||||
we’re checking if the class has a custom implementation of the <code class="literal">toString()</code> method.</p><p>So executing such code:</p><pre class="programlisting">Runnable runnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceRunnable(tracer, spanNamer, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Runnable() {
|
||||
we’re checking if the class has a custom implementation of the <code class="literal">toString()</code> method.</p><p>So executing such code:</p><pre class="programlisting">Runnable runnable = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> TraceRunnable(tracer, spanNamer, errorParser, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">new</span> Runnable() {
|
||||
<em><span class="hl-annotation" style="color: gray">@Override</span></em> <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">// perform logic</span>
|
||||
}
|
||||
@@ -24,4 +25,4 @@ we’re checking if the class has a custom implementation of the <code class
|
||||
});
|
||||
Future<?> future = executorService.submit(runnable);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ... some additional logic ...</span>
|
||||
future.get();</pre><p>will lead in creating a span named <code class="literal">calculateTax</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__span_lifecycle.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__managing_spans_with_annotations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6. Span lifecycle </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"> 8. Managing spans with annotations</td></tr></table></div></body></html>
|
||||
future.get();</pre><p>will lead in creating a span named <code class="literal">calculateTax</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__span_lifecycle.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__managing_spans_with_annotations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">9. Span lifecycle </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"> 11. Managing spans with annotations</td></tr></table></div></body></html>
|
||||
98
multi/multi__propagation.html
Normal file
98
multi/multi__propagation.html
Normal file
@@ -0,0 +1,98 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>5. Propagation</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__sampling.html" title="4. Sampling"><link rel="next" href="multi__current_tracing_component.html" title="6. Current Tracing Component"></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">5. Propagation</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__sampling.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__current_tracing_component.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_propagation" href="#_propagation"></a>5. Propagation</h1></div></div></div><p>Propagation is needed to ensure activity originating from the same root
|
||||
are collected together in the same trace. The most common propagation
|
||||
approach is to copy a trace context from a client sending an RPC request
|
||||
to a server receiving it.</p><p>For example, when an downstream Http call is made, its trace context is
|
||||
sent along with it, encoded as request headers:</p><pre class="screen"> Client Span Server Span
|
||||
┌──────────────────┐ ┌──────────────────┐
|
||||
│ │ │ │
|
||||
│ TraceContext │ Http Request Headers │ TraceContext │
|
||||
│ ┌──────────────┐ │ ┌───────────────────┐ │ ┌──────────────┐ │
|
||||
│ │ TraceId │ │ │ X─B3─TraceId │ │ │ TraceId │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ │ ParentSpanId │ │ Extract │ X─B3─ParentSpanId │ Inject │ │ ParentSpanId │ │
|
||||
│ │ ├─┼─────────>│ ├────────┼>│ │ │
|
||||
│ │ SpanId │ │ │ X─B3─SpanId │ │ │ SpanId │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ │ Sampled │ │ │ X─B3─Sampled │ │ │ Sampled │ │
|
||||
│ └──────────────┘ │ └───────────────────┘ │ └──────────────┘ │
|
||||
│ │ │ │
|
||||
└──────────────────┘ └──────────────────┘</pre><p>The names above are from <a class="link" href="https://github.com/openzipkin/b3-propagation" target="_top">B3 Propagation</a>,
|
||||
which is built-in to Brave and has implementations in many languages and
|
||||
frameworks.</p><p>Most users will use a framework interceptor which automates propagation.
|
||||
Here’s how they might work internally.</p><p>Here’s what client-side propagation might look like</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// configure a function that injects a trace context into a request</span>
|
||||
injector = tracing.propagation().injector(Request.Builder::addHeader);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// before a request is sent, add the current span's context to it</span>
|
||||
injector.inject(span.context(), request);</pre><p>Here’s what server-side propagation might look like</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// configure a function that extracts the trace context from a request</span>
|
||||
extracted = tracing.propagation().extractor(Request::getHeader);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when a server receives a request, it joins or starts a new trace</span>
|
||||
span = tracer.nextSpan(extracted, request);</pre><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_propagating_extra_fields" href="#_propagating_extra_fields"></a>5.1 Propagating extra fields</h2></div></div></div><p>Sometimes you need to propagate extra fields, such as a request ID or an alternate trace context.
|
||||
For example, if you are in a Cloud Foundry environment, you might want to pass the request ID:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// when you initialize the builder, define the extra field you want to propagate</span>
|
||||
tracingBuilder.propagationFactory(
|
||||
ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"x-vcap-request-id"</span>)
|
||||
);
|
||||
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// later, you can tag that request ID or use it in log correlation</span>
|
||||
requestId = ExtraFieldPropagation.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"x-vcap-request-id"</span>);</pre><p>You may also need to propagate a trace context you aren’t using. For example, you may be in an
|
||||
Amazon Web Services environment, but not reporting data to X-Ray. To ensure X-Ray can co-exist
|
||||
correctly, pass-through its tracing header like so.</p><pre class="programlisting">tracingBuilder.propagationFactory(
|
||||
ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"x-amzn-trace-id"</span>)
|
||||
);</pre><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_prefixed_fields" href="#_prefixed_fields"></a>5.1.1 Prefixed fields</h3></div></div></div><p>You can also prefix fields, if they follow a common pattern. For example, the following will
|
||||
propagate the field "x-vcap-request-id" as-is, but send the fields "country-code" and "user-id"
|
||||
on the wire as "x-baggage-country-code" and "x-baggage-user-id" respectively.</p><p>Setup your tracing instance with allowed fields:</p><pre class="programlisting">tracingBuilder.propagationFactory(
|
||||
ExtraFieldPropagation.newFactoryBuilder(B3Propagation.FACTORY)
|
||||
.addField(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"x-vcap-request-id"</span>)
|
||||
.addPrefixedFields(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"baggage-"</span>, Arrays.asList(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"country-code"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"user-id"</span>))
|
||||
.build()
|
||||
);</pre><p>Later, you can call below to affect the country code of the current trace context</p><pre class="programlisting">ExtraFieldPropagation.set(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"country-code"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FO"</span>);
|
||||
String countryCode = ExtraFieldPropagation.get(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"country-code"</span>);</pre><p>Or, if you have a reference to a trace context, use it explicitly</p><pre class="programlisting">ExtraFieldPropagation.set(span.context(), <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"country-code"</span>, <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"FO"</span>);
|
||||
String countryCode = ExtraFieldPropagation.get(span.context(), <span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"country-code"</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>In comparison to previous versions of Sleuth, with
|
||||
Brave it’s required to pass the list of baggage keys.
|
||||
There are two properties to achieve this. Via the <code class="literal">spring.sleuth.baggage-keys</code> you set keys
|
||||
that will get prefixed with <code class="literal">baggage-</code> for http calls and <code class="literal">baggage_</code> for messaging. You can also pass
|
||||
a list of prefixed keys that will be whitelisted without any prefix via
|
||||
<code class="literal">spring.sleuth.prefixed-keys</code> property.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_extracting_a_propagated_context" href="#_extracting_a_propagated_context"></a>5.1.2 Extracting a propagated context</h3></div></div></div><p>The <code class="literal">TraceContext.Extractor<C></code> reads trace identifiers and sampling status
|
||||
from an incoming request or message. The carrier is usually a request object
|
||||
or headers.</p><p>This utility is used in standard instrumentation like [HttpServerHandler](../instrumentation/http/src/main/java/sleuth/http/HttpServerHandler.java),
|
||||
but can also be used for custom RPC or messaging code.</p><p><code class="literal">TraceContextOrSamplingFlags</code> is usually only used with <code class="literal">Tracer.nextSpan(extracted)</code>, unless you are
|
||||
sharing span IDs between a client and a server.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_sharing_span_ids_between_client_and_server" href="#_sharing_span_ids_between_client_and_server"></a>5.1.3 Sharing span IDs between client and server</h3></div></div></div><p>A normal instrumentation pattern is creating a span representing the server
|
||||
side of an RPC. <code class="literal">Extractor.extract</code> might return a complete trace context when
|
||||
applied to an incoming client request. <code class="literal">Tracer.joinSpan</code> attempts to continue
|
||||
the this trace, using the same span ID if supported, or creating a child span
|
||||
if not. When span ID is shared, data reported includes a flag saying so.</p><p>Here’s an example of B3 propagation:</p><pre class="screen"> ┌───────────────────┐ ┌───────────────────┐
|
||||
Incoming Headers │ TraceContext │ │ TraceContext │
|
||||
┌───────────────────┐(extract)│ ┌───────────────┐ │(join)│ ┌───────────────┐ │
|
||||
│ X─B3-TraceId │─────────┼─┼> TraceId │ │──────┼─┼> TraceId │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ X─B3-ParentSpanId │─────────┼─┼> ParentSpanId │ │──────┼─┼> ParentSpanId │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ X─B3-SpanId │─────────┼─┼> SpanId │ │──────┼─┼> SpanId │ │
|
||||
└───────────────────┘ │ │ │ │ │ │ │ │
|
||||
│ │ │ │ │ │ Shared: true │ │
|
||||
│ └───────────────┘ │ │ └───────────────┘ │
|
||||
└───────────────────┘ └───────────────────┘</pre><p>Some propagation systems only forward the parent span ID, detected when
|
||||
<code class="literal">Propagation.Factory.supportsJoin() == false</code>. In this case, a new span ID is
|
||||
always provisioned and the incoming context determines the parent ID.</p><p>Here’s an example of AWS propagation:</p><pre class="screen"> ┌───────────────────┐ ┌───────────────────┐
|
||||
x-amzn-trace-id │ TraceContext │ │ TraceContext │
|
||||
┌───────────────────┐(extract)│ ┌───────────────┐ │(join)│ ┌───────────────┐ │
|
||||
│ Root │─────────┼─┼> TraceId │ │──────┼─┼> TraceId │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ Parent │─────────┼─┼> SpanId │ │──────┼─┼> ParentSpanId │ │
|
||||
└───────────────────┘ │ └───────────────┘ │ │ │ │ │
|
||||
└───────────────────┘ │ │ SpanId: New │ │
|
||||
│ └───────────────┘ │
|
||||
└───────────────────┘</pre><p>Note: Some span reporters do not support sharing span IDs. For example, if you
|
||||
set <code class="literal">Tracing.Builder.spanReporter(amazonXrayOrGoogleStackdrive)</code>, disable join
|
||||
via <code class="literal">Tracing.Builder.supportsJoin(false)</code>. This will force a new child span on
|
||||
<code class="literal">Tracer.joinSpan()</code>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="_implementing_propagation" href="#_implementing_propagation"></a>5.1.4 Implementing Propagation</h3></div></div></div><p><code class="literal">TraceContext.Extractor<C></code> is implemented by a <code class="literal">Propagation.Factory</code> plugin. Internally, this code
|
||||
will create the union type <code class="literal">TraceContextOrSamplingFlags</code> with one of the following:
|
||||
* <code class="literal">TraceContext</code> if trace and span IDs were present.
|
||||
* <code class="literal">TraceIdContext</code> if a trace ID was present, but not span IDs.
|
||||
* <code class="literal">SamplingFlags</code> if no identifiers were present</p><p>Some <code class="literal">Propagation</code> implementations carry extra data from point of extraction (ex reading incoming
|
||||
headers) to injection (ex writing outgoing headers). For example, it might carry a request ID. When
|
||||
implementations have extra data, here’s how they handle it.
|
||||
* If a <code class="literal">TraceContext</code> was extracted, add the extra data as <code class="literal">TraceContext.extra()</code>
|
||||
* Otherwise, add it as <code class="literal">TraceContextOrSamplingFlags.extra()</code>, which <code class="literal">Tracer.nextSpan</code> handles.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__sampling.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__current_tracing_component.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">4. Sampling </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"> 6. Current Tracing Component</td></tr></table></div></body></html>
|
||||
@@ -1,3 +1,3 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>14. Running examples</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__integrations.html" title="13. Integrations"></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">14. Running examples</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__integrations.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> </td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_running_examples" href="#_running_examples"></a>14. Running examples</h1></div></div></div><p>You can find the running examples deployed in the <a class="link" href="https://run.pivotal.io/" target="_top">Pivotal Web Services</a>. Check them out in the following links:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="http://docssleuth-zipkin-server.cfapps.io/" target="_top">Zipkin for apps presented in the samples to the top</a></li><li class="listitem"><a class="link" href="http://docsbrewing-zipkin-server.cfapps.io/" target="_top">Zipkin for Brewery on PWS</a>, its <a class="link" href="https://github.com/spring-cloud-samples/brewery" target="_top">Github Code</a></li></ul></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__integrations.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top">13. Integrations </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"> </td></tr></table></div></body></html>
|
||||
<title>16. Running examples</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__integrations.html" title="15. Integrations"></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">16. Running examples</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__integrations.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> </td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_running_examples" href="#_running_examples"></a>16. Running examples</h1></div></div></div><p>You can find the running examples deployed in the <a class="link" href="https://run.pivotal.io/" target="_top">Pivotal Web Services</a>. Check them out in the following links:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="http://docssleuth-zipkin-server.cfapps.io/" target="_top">Zipkin for apps presented in the samples to the top</a></li><li class="listitem"><a class="link" href="http://docsbrewing-zipkin-server.cfapps.io/" target="_top">Zipkin for Brewery on PWS</a>, its <a class="link" href="https://github.com/spring-cloud-samples/brewery" target="_top">Github Code</a></li></ul></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__integrations.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top">15. Integrations </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"> </td></tr></table></div></body></html>
|
||||
@@ -1,26 +1,45 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>4. Sampling</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__features.html" title="3. Features"><link rel="next" href="multi__instrumentation.html" title="5. Instrumentation"></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">4. Sampling</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__features.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__instrumentation.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_sampling" href="#_sampling"></a>4. Sampling</h1></div></div></div><p>In distributed tracing the data volumes can be very high so sampling
|
||||
can be important (you usually don’t need to export all spans to get a
|
||||
good picture of what is happening). Spring Cloud Sleuth has a
|
||||
<code class="literal">Sampler</code> strategy that you can implement to take control of the
|
||||
sampling algorithm. Samplers do not stop span (correlation) ids from
|
||||
being generated, but they do prevent the tags and events being
|
||||
attached and exported. By default you get a strategy that continues to
|
||||
trace if a span is already active, but new ones are always marked as
|
||||
non-exportable. If all your apps run with this sampler you will see
|
||||
traces in logs, but not in any remote store. For testing the default
|
||||
is often enough, and it probably is all you need if you are only using
|
||||
the logs (e.g. with an ELK aggregator). If you are exporting span data
|
||||
to Zipkin or Spring Cloud Stream, there is also an <code class="literal">AlwaysSampler</code>
|
||||
that exports everything and a <code class="literal">PercentageBasedSampler</code> that samples a
|
||||
fixed fraction of spans.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>the <code class="literal">PercentageBasedSampler</code> is the default if you are using
|
||||
<code class="literal">spring-cloud-sleuth-zipkin</code> or <code class="literal">spring-cloud-sleuth-stream</code>. You can
|
||||
configure the exports using <code class="literal">spring.sleuth.sampler.percentage</code>. The passed
|
||||
value needs to be a double from <code class="literal">0.0</code> to <code class="literal">1.0</code> so it’s not a percentage.
|
||||
For backwards compatibility reasons we’re not changing the property name.</p></td></tr></table></div><p>A sampler can be installed just by creating a bean definition, e.g:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<title>4. Sampling</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__features.html" title="3. Features"><link rel="next" href="multi__propagation.html" title="5. Propagation"></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">4. Sampling</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__features.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__propagation.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_sampling" href="#_sampling"></a>4. Sampling</h1></div></div></div><p>Sampling may be employed to reduce the data collected and reported out
|
||||
of process. When a span isn’t sampled, it adds no overhead (noop).</p><p>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.</p><p>By default, there’s a global sampler that applies a single rate to all
|
||||
traced operations. <code class="literal">Tracer.Builder.sampler</code> is how you indicate this,
|
||||
and it defaults to trace every request.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_declarative_sampling" href="#_declarative_sampling"></a>4.1 Declarative sampling</h2></div></div></div><p>Some need to sample based on the type or annotations of a java method.</p><p>Most users will use a framework interceptor which automates this sort of
|
||||
policy. Here’s how they might work internally.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// derives a sample rate from an annotation on a java method</span>
|
||||
DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sampleRate);
|
||||
|
||||
<em><span class="hl-annotation" style="color: gray">@Around("@annotation(traced)")</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Object traceThing(ProceedingJoinPoint pjp, Traced traced) <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">throws</span> Throwable {
|
||||
Span span = tracing.tracer().newTrace(sampler.sample(traced))...
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> pjp.proceed();
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
span.finish();
|
||||
}
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_custom_sampling" href="#_custom_sampling"></a>4.2 Custom sampling</h2></div></div></div><p>You may want to apply different policies depending on what the operation
|
||||
is. 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.</p><p>Most users will use a framework interceptor which automates this sort of
|
||||
policy. Here’s how they might work internally.</p><pre class="programlisting">Span newTrace(Request input) {
|
||||
SamplingFlags flags = SamplingFlags.NONE;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/experimental"</span>)) {
|
||||
flags = SamplingFlags.SAMPLED;
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">else</span> <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (input.url().startsWith(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"/static"</span>)) {
|
||||
flags = SamplingFlags.NOT_SAMPLED;
|
||||
}
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> tracer.newTrace(flags);
|
||||
}</pre><p>Note: the above is the basis for the built-in <a class="link" href="https://github.com/openzipkin/sleuth/tree/master/instrumentation/http" target="_top">http sampler</a></p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="_sampling_in_spring_cloud_sleuth" href="#_sampling_in_spring_cloud_sleuth"></a>4.3 Sampling in Spring Cloud Sleuth</h2></div></div></div><p>Spring Cloud Sleuth by default sets all spans to non-exportable.
|
||||
That means that you will see traces in logs, but not in any remote store.
|
||||
For testing the default is often enough, and it probably is all you need
|
||||
if you are only using the logs (e.g. with an ELK aggregator). If you are
|
||||
exporting span data to Zipkin, there is also an <code class="literal">Sampler.ALWAYS_SAMPLE</code>
|
||||
that exports everything and a <code class="literal">ProbabilityBasedSampler</code> that samples a
|
||||
fixed fraction of spans.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top"><p>The <code class="literal">ProbabilityBasedSampler</code> is the default if you are using
|
||||
<code class="literal">spring-cloud-sleuth-zipkin</code>. You can
|
||||
configure the exports using <code class="literal">spring.sleuth.sampler.probability</code>. The passed
|
||||
value needs to be a double from <code class="literal">0.0</code> to <code class="literal">1.0</code>.</p></td></tr></table></div><p>A sampler can be installed just by creating a bean definition, e.g:</p><pre class="programlisting"><em><span class="hl-annotation" style="color: gray">@Bean</span></em>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">public</span> Sampler defaultSampler() {
|
||||
<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> AlwaysSampler();
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">return</span> Sampler.ALWAYS_SAMPLE;
|
||||
}</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>You can set the HTTP header <code class="literal">X-B3-Flags</code> to <code class="literal">1</code> or when doing messaging you can
|
||||
set <code class="literal">spanFlags</code> header to <code class="literal">1</code>. Then the current span will be forced to be exportable
|
||||
regardless of the sampling decision.</p></td></tr></table></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__features.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__instrumentation.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3. Features </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"> 5. Instrumentation</td></tr></table></div></body></html>
|
||||
regardless of the sampling decision.</p></td></tr></table></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__features.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__propagation.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3. Features </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"> 5. Propagation</td></tr></table></div></body></html>
|
||||
@@ -1,7 +1,7 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>10. Sending spans to Zipkin</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__customizations.html" title="9. Customizations"><link rel="next" href="multi__span_data_as_messages.html" title="11. Span Data as Messages"></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">10. Sending spans to Zipkin</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__customizations.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__span_data_as_messages.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_sending_spans_to_zipkin" href="#_sending_spans_to_zipkin"></a>10. Sending spans to Zipkin</h1></div></div></div><p>By default if you add <code class="literal">spring-cloud-starter-zipkin</code> as a dependency to your project,
|
||||
<title>13. Sending spans to Zipkin</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__customizations.html" title="12. Customizations"><link rel="next" href="multi__zipkin_stream_span_consumer.html" title="14. Zipkin Stream Span Consumer"></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">13. Sending spans to Zipkin</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__customizations.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__zipkin_stream_span_consumer.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_sending_spans_to_zipkin" href="#_sending_spans_to_zipkin"></a>13. Sending spans to Zipkin</h1></div></div></div><p>By default if you add <code class="literal">spring-cloud-starter-zipkin</code> as a dependency to your project,
|
||||
when the span is closed, it will be sent to Zipkin over HTTP. The communication
|
||||
is asynchronous. You can configure the URL by setting the <code class="literal">spring.zipkin.baseUrl</code>
|
||||
property as follows:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.zipkin.baseUrl</span>: http://<span class="hl-number">192.168</span>.<span class="hl-number">99.100</span>:<span class="hl-number">9411</span>/</pre><p>If you want to find Zipkin via service discovery it’s enough to pass the
|
||||
Zipkin’s service id inside the URL (example for <code class="literal">zipkinserver</code> service id)</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.zipkin.baseUrl</span>: http://zipkinserver/</pre></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__customizations.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__span_data_as_messages.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">9. Customizations </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"> 11. Span Data as Messages</td></tr></table></div></body></html>
|
||||
Zipkin’s service id inside the URL (example for <code class="literal">zipkinserver</code> service id)</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-attribute">spring.zipkin.baseUrl</span>: http://zipkinserver/</pre></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__customizations.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__zipkin_stream_span_consumer.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">12. Customizations </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"> 14. Zipkin Stream Span Consumer</td></tr></table></div></body></html>
|
||||
@@ -1,63 +1,63 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>6. Span lifecycle</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__instrumentation.html" title="5. Instrumentation"><link rel="next" href="multi__naming_spans.html" title="7. Naming spans"></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">6. Span lifecycle</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__instrumentation.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__naming_spans.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_span_lifecycle" href="#_span_lifecycle"></a>6. Span lifecycle</h1></div></div></div><p>You can do the following operations on the Span by means of <span class="strong"><strong>org.springframework.cloud.sleuth.Tracer</strong></span> interface:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="multi__span_lifecycle.html#creating-and-closing-spans" title="6.1 Creating and closing spans">start</a> - when you start a span its name is assigned and start timestamp is recorded.</li><li class="listitem"><a class="link" href="multi__span_lifecycle.html#creating-and-closing-spans" title="6.1 Creating and closing spans">close</a> - the span gets finished (the end time of the span is recorded) and if
|
||||
the span is <span class="strong"><strong>exportable</strong></span> then it will be eligible for collection to Zipkin.
|
||||
The span is also removed from the current thread.</li><li class="listitem"><a class="link" href="multi__span_lifecycle.html#continuing-spans" title="6.2 Continuing spans">continue</a> - a new instance of span will be created whereas it will be a copy of the
|
||||
one that it continues.</li><li class="listitem"><a class="link" href="multi__span_lifecycle.html#continuing-spans" title="6.2 Continuing spans">detach</a> - the span doesn’t get stopped or closed. It only gets removed from the current thread.</li><li class="listitem"><a class="link" href="multi__span_lifecycle.html#creating-spans-with-explicit-parent" title="6.3 Creating spans with an explicit parent">create with explicit parent</a> - you can create a new span and set an explicit parent to it</li></ul></div><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>Spring creates the instance of <code class="literal">Tracer</code> for you. In order to use it all you need is to just autowire it.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="creating-and-closing-spans" href="#creating-and-closing-spans"></a>6.1 Creating and closing spans</h2></div></div></div><p>You can manually create spans by using the <span class="strong"><strong>Tracer</strong></span> interface.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Start a span. If there was a span present in this thread it will become</span>
|
||||
<title>9. Span lifecycle</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__instrumentation.html" title="8. Instrumentation"><link rel="next" href="multi__naming_spans.html" title="10. Naming spans"></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">9. Span lifecycle</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__instrumentation.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__naming_spans.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_span_lifecycle" href="#_span_lifecycle"></a>9. Span lifecycle</h1></div></div></div><p>You can do the following operations on the Span by means of <span class="strong"><strong>brave.Tracer</strong></span>:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><a class="link" href="multi__span_lifecycle.html#creating-and-finishing-spans" title="9.1 Creating and finishing spans">start</a> - when you start a span its name is assigned and start timestamp is recorded.</li><li class="listitem"><a class="link" href="multi__span_lifecycle.html#creating-and-finishing-spans" title="9.1 Creating and finishing spans">close</a> - the span gets finished (the end time of the span is recorded) and if
|
||||
the span is <span class="strong"><strong>sampled</strong></span> then it will be eligible for collection to e.g. Zipkin.</li><li class="listitem"><a class="link" href="multi__span_lifecycle.html#continuing-spans" title="9.2 Continuing spans">continue</a> - a new instance of span will be created whereas it will be a copy of the
|
||||
one that it continues.</li><li class="listitem"><a class="link" href="multi__span_lifecycle.html#continuing-spans" title="9.2 Continuing spans">detach</a> - the span doesn’t get stopped or closed. It only gets removed from the current thread.</li><li class="listitem"><a class="link" href="multi__span_lifecycle.html#creating-spans-with-explicit-parent" title="9.3 Creating spans with an explicit parent">create with explicit parent</a> - you can create a new span and set an explicit parent to it</li></ul></div><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>Spring Cloud Sleuth creates the instance of <code class="literal">Tracer</code> for you. In order to use it,
|
||||
all you need is to just autowire it.</p></td></tr></table></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="creating-and-finishing-spans" href="#creating-and-finishing-spans"></a>9.1 Creating and finishing spans</h2></div></div></div><p>You can manually create spans by using the <span class="strong"><strong>Tracer</strong></span>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Start a span. If there was a span present in this thread it will become</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the `newSpan`'s parent.</span>
|
||||
Span newSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.createSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateTax"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
Span newSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.nextSpan().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateTax"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> (Tracer.SpanInScope ws = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.withSpanInScope(newSpan.start())) {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// You can tag a span</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.addTag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"taxValue"</span>, taxValue);
|
||||
newSpan.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"taxValue"</span>, taxValue);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// You can log an event on a span</span>
|
||||
newSpan.logEvent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"taxCalculated"</span>);
|
||||
newSpan.annotate(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"taxCalculated"</span>);
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Once done remember to close the span. This will allow collecting</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Once done remember to finish the span. This will allow collecting</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the span to send it to Zipkin</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.close(newSpan);
|
||||
newSpan.finish();
|
||||
}</pre><p>In this example we could see how to create a new instance of span. Assuming that there already
|
||||
was a span present in this thread then it would become the parent of that span.</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>Always clean after you create a span! Don’t forget to close a span if you want to send it to Zipkin.</p></td></tr></table></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>If your span contains a name greater than 50 chars, then that name will
|
||||
was a span present in this thread then it would become the parent of that span.</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>Always clean after you create a span! Don’t forget to finish a span if you want to send it to Zipkin.</p></td></tr></table></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>If your span contains a name greater than 50 chars, then that name will
|
||||
be truncated to 50 chars. Your names have to be explicit and concrete. Big names lead to
|
||||
latency issues and sometimes even thrown exceptions.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="continuing-spans" href="#continuing-spans"></a>6.2 Continuing spans</h2></div></div></div><p>Sometimes you don’t want to create a new span but you want to continue one. Example of such a
|
||||
latency issues and sometimes even thrown exceptions.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="continuing-spans" href="#continuing-spans"></a>9.2 Continuing spans</h2></div></div></div><p>Sometimes you don’t want to create a new span but you want to continue one. Example of such a
|
||||
situation might be (of course it all depends on the use-case):</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><span class="strong"><strong>AOP</strong></span> - If there was already a span created before an aspect was reached then you might not want to create a new span.</li><li class="listitem"><span class="strong"><strong>Hystrix</strong></span> - executing a Hystrix command is most likely a logical part of the current processing. It’s in fact
|
||||
only a technical implementation detail that you wouldn’t necessarily want to reflect in tracing as a separate being.</li></ul></div><p>The continued instance of span is equal to the one that it continues:</p><pre class="programlisting">Span continuedSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.continueSpan(spanToContinue);
|
||||
assertThat(continuedSpan).isEqualTo(spanToContinue);</pre><p>To continue a span you can use the <span class="strong"><strong>Tracer</strong></span> interface.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// let's assume that we're in a thread Y and we've received</span>
|
||||
only a technical implementation detail that you wouldn’t necessarily want to reflect in tracing as a separate being.</li></ul></div><p>To continue a span you can use <span class="strong"><strong>brave.Tracer</strong></span>.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// let's assume that we're in a thread Y and we've received</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the `initialSpan` from thread X</span>
|
||||
Span continuedSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.continueSpan(initialSpan);
|
||||
Span continuedSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.joinSpan(newSpan.context());
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// You can tag a span</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.addTag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"taxValue"</span>, taxValue);
|
||||
continuedSpan.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"taxValue"</span>, taxValue);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// You can log an event on a span</span>
|
||||
continuedSpan.logEvent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"taxCalculated"</span>);
|
||||
continuedSpan.annotate(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"taxCalculated"</span>);
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Once done remember to detach the span. That way you'll</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// safely remove it from the current thread without closing it</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.detach(continuedSpan);
|
||||
}</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>Always clean after you create a span! Don’t forget to detach a span if some work was done started in one
|
||||
thread (e.g. thread X) and it’s waiting for other threads (e.g. Y, Z) to finish.
|
||||
Then the spans in the threads Y, Z should be detached at the end of their work. When the results are collected
|
||||
the span in thread X should be closed.</p></td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="creating-spans-with-explicit-parent" href="#creating-spans-with-explicit-parent"></a>6.3 Creating spans with an explicit parent</h2></div></div></div><p>There is a possibility that you want to start a new span and provide an explicit parent of that span.
|
||||
Let’s assume that the parent of a span is in one thread and you want to start a new span in another thread. The
|
||||
<code class="literal">startSpan</code> method of the <code class="literal">Tracer</code> interface is the method you are looking for.</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// let's assume that we're in a thread Y and we've received</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Once done remember to flush the span. That means that</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// it will get reported but the span itself is not yet finished</span>
|
||||
continuedSpan.flush();
|
||||
}</pre></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="creating-spans-with-explicit-parent" href="#creating-spans-with-explicit-parent"></a>9.3 Creating spans with an explicit parent</h2></div></div></div><p>There is a possibility that you want to start a new span and provide an explicit parent of that span.
|
||||
Let’s assume that the parent of a span is in one thread and you want to start a new span in another thread.
|
||||
In Brave, whenever you call <code class="literal">nextSpan()</code>, it’s creating one in reference
|
||||
to the span being currently in scope. It’s enough to just put
|
||||
the span in scope and then call <code class="literal">nextSpan()</code>, as presented in the example below:</p><pre class="programlisting"><span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// let's assume that we're in a thread Y and we've received</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the `initialSpan` from thread X. `initialSpan` will be the parent</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// of the `newSpan`</span>
|
||||
Span newSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.createSpan(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateCommission"</span>, initialSpan);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> {
|
||||
Span newSpan = null;
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">try</span> (Tracer.SpanInScope ws = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.withSpanInScope(initialSpan)) {
|
||||
newSpan = <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.nextSpan().name(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"calculateCommission"</span>);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// You can tag a span</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.addTag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"commissionValue"</span>, commissionValue);
|
||||
newSpan.tag(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"commissionValue"</span>, commissionValue);
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// ...</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// You can log an event on a span</span>
|
||||
newSpan.logEvent(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"commissionCalculated"</span>);
|
||||
newSpan.annotate(<span xmlns:d="http://docbook.org/ns/docbook" class="hl-string">"commissionCalculated"</span>);
|
||||
} <span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">finally</span> {
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Once done remember to close the span. This will allow collecting</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// Once done remember to finish the span. This will allow collecting</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// the span to send it to Zipkin. The tags and events set on the</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-comment">// newSpan will not be present on the parent</span>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">this</span>.tracer.close(newSpan);
|
||||
}</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>After having created such a span remember to close it. Otherwise you will see a lot of warnings in your logs
|
||||
related to the fact that you have a span present in the current thread other than the one you’re trying to close.
|
||||
What’s worse your spans won’t get closed properly thus will not get collected to Zipkin.</p></td></tr></table></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__instrumentation.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__naming_spans.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">5. Instrumentation </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"> 7. Naming spans</td></tr></table></div></body></html>
|
||||
<span xmlns:d="http://docbook.org/ns/docbook" class="hl-keyword">if</span> (newSpan != null) {
|
||||
newSpan.finish();
|
||||
}
|
||||
}</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>After having created such a span remember to finish it, otherwise it will not get
|
||||
reported to e.g. Zipkin</p></td></tr></table></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__instrumentation.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__naming_spans.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8. Instrumentation </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"> 10. Naming spans</td></tr></table></div></body></html>
|
||||
7
multi/multi__zipkin_stream_span_consumer.html
Normal file
7
multi/multi__zipkin_stream_span_consumer.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<html><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<title>14. Zipkin Stream Span Consumer</title><link rel="stylesheet" type="text/css" href="css/manual-multipage.css"><meta name="generator" content="DocBook XSL Stylesheets V1.78.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__sending_spans_to_zipkin.html" title="13. Sending spans to Zipkin"><link rel="next" href="multi__integrations.html" title="15. Integrations"></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">14. Zipkin Stream Span Consumer</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="multi__sending_spans_to_zipkin.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="multi__integrations.html">Next</a></td></tr></table><hr></div><div class="chapter"><div class="titlepage"><div><div><h1 class="title"><a name="_zipkin_stream_span_consumer" href="#_zipkin_stream_span_consumer"></a>14. Zipkin Stream Span Consumer</h1></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 suggested approach is to use the Zipkin’s
|
||||
native support for message based span sending. Starting from
|
||||
Edgware Zipkin Stream server is deprecated and in Finchley
|
||||
it got removed.</p></td></tr></table></div><p>Please refer to the <a class="link" href="http://cloud.spring.io/spring-cloud-static/Dalston.SR4/multi/multi__span_data_as_messages.html#_zipkin_consumer" target="_top">Dalston Documentaion</a>
|
||||
on how to create a Stream Zipkin server.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="multi__sending_spans_to_zipkin.html">Prev</a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="multi__integrations.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">13. Sending spans to Zipkin </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"> 15. Integrations</td></tr></table></div></body></html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user