+
diff --git a/images/dependencies.png b/images/dependencies.png index 324a10062..d0eceb6fb 100644 Binary files a/images/dependencies.png and b/images/dependencies.png differ diff --git a/images/zipkin-error-trace-screenshot.png b/images/zipkin-error-trace-screenshot.png new file mode 100644 index 000000000..02a7270eb Binary files /dev/null and b/images/zipkin-error-trace-screenshot.png differ diff --git a/images/zipkin-error-traces.png b/images/zipkin-error-traces.png new file mode 100644 index 000000000..233b0cbf3 Binary files /dev/null and b/images/zipkin-error-traces.png differ diff --git a/images/zipkin-trace-screenshot.png b/images/zipkin-trace-screenshot.png index 61b7ff769..b230a19a3 100644 Binary files a/images/zipkin-trace-screenshot.png and b/images/zipkin-trace-screenshot.png differ diff --git a/images/zipkin-traces.png b/images/zipkin-traces.png index 4875ca69b..421bddec8 100644 Binary files a/images/zipkin-traces.png and b/images/zipkin-traces.png differ diff --git a/images/zipkin-ui.png b/images/zipkin-ui.png index ea99bc100..6bfe38e67 100644 Binary files a/images/zipkin-ui.png and b/images/zipkin-ui.png differ diff --git a/spring-cloud-sleuth.html b/spring-cloud-sleuth.html index 89062e3c0..aa6599367 100644 --- a/spring-cloud-sleuth.html +++ b/spring-cloud-sleuth.html @@ -431,16 +431,13 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
1.2.0.BUILD-SNAPSHOT
+1.1.1.BUILD-SNAPSHOT
Spring Cloud Sleuth implements a distributed tracing solution for Spring Cloud.
@@ -595,7 +591,7 @@ will receive the whole time needed by the client to receive the response from th
+
+
Altogether there are 10 spans . If you go to traces in Zipkin you will see this number:
+Altogether there are 7 spans . If you go to traces in Zipkin you will see this number in the second trace:
+
However if you pick a particular trace then you will see 7 spans:
+However if you pick a particular trace then you will see 4 spans:
+
In the image depicting the visualization of what Span and Trace is you can see 20 -colorful labels. How does it happen that in Zipkin 10 spans are received?
+Why is there a difference between the 7 and 4 spans in this case?
2 span A labels signify span started and closed. Upon closing a single span is sent to Zipkin.
+2 spans come from http:/start span. It has the Server Received (SR) and Server Sent (SS) annotations.
4 span B labels are in fact are single span with 4 annotations. However this span is composed of -two separate instances. One sent from service 1 and one from service 2. So in fact two span instances will be sent -to Zipkin and merged there.
+2 spans come from the RPC call from service1 to service2 to the http:/foo endpoint. It has the Client Sent (CS)
+and Client Received (CR) annotations on service1 side. It also has Server Received (SR) and Server Sent (SS) annotations
+on the service2 side. Physically there are 2 spans but they form 1 logical span related to an RPC call.
2 span C labels signify span started and closed. Upon closing a single span is sent to Zipkin.
+2 spans come from the RPC call from service2 to service3 to the http:/bar endpoint. It has the Client Sent (CS)
+and Client Received (CR) annotations on service2 side. It also has Server Received (SR) and Server Sent (SS) annotations
+on the service3 side. Physically there are 2 spans but they form 1 logical span related to an RPC call.
4 span B labels are in fact are single span with 4 annotations. However this span is composed of -two separate instances. One sent from service 2 and one from service 3. So in fact two span instances will be sent -to Zipkin and merged there.
-2 span E labels signify span started and closed. Upon closing a single span is sent to Zipkin.
-4 span B labels are in fact are single span with 4 annotations. However this span is composed of -two separate instances. One sent from service 2 and one from service 4. So in fact two span instances will be sent -to Zipkin and merged there.
-2 span G labels signify span started and closed. Upon closing a single span is sent to Zipkin.
+2 spans come from the RPC call from service2 to service4 to the http:/baz endpoint. It has the Client Sent (CS)
+and Client Received (CR) annotations on service2 side. It also has Server Received (SR) and Server Sent (SS) annotations
+on the service4 side. Physically there are 2 spans but they form 1 logical span related to an RPC call.
So 1 span from A, 2 spans from B, 1 span from C, 2 spans from D, 1 span from E, 2 spans from F and 1 from G. -Altogether 10 spans.
+So if we count the physical spans we have 1 from http:/start, 2 from service1 calling service2, 2 form service2
+calling service3 and 2 from service2 calling service4. Altogether 7 spans.
Logically we see the information of Total Spans: 4 because we have 1 span related to the incoming request
+to service1 and 3 spans related to RPC calls.
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.
+If you click that trace then you’ll see a similar picture
Then if you click on one of the spans you’ll see the following
+
+As you can see you can easily see the reason for an error and the whole stacktrace related to it.
+
+
+
groupId:artifactId:versionLogback setup
Below you can find an example of a Logback configuration (file named https://github.com/spring-cloud-samples/sleuth-documentation-apps/blob/master/service1/src/main/resources/logback-spring.xml[logback-spring.xml]) that:
Below you can find an example of a Logback configuration (file named logback-spring.xml) that:
logback-spring.xml then you have to
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.
-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 baggage- and for messaging it starts with baggage_.
|
- Important
- |
--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. - | -
Example of setting baggage on a span:
-Span initialSpan = this.tracer.createSpan("span");
-initialSpan.setBaggageItem("foo", "bar");
-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.
-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.
-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.
-@Autowired Tracer tracer;
-
-Span span = tracer.getCurrentSpan();
-String baggageKey = "key";
-String baggageValue = "foo";
-span.setBaggageItem(baggageKey, baggageValue);
-tracer.addTag(baggageKey, baggageValue);
-spring-cloud-starter-sleuth module to your project.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
- <version>Camden.RELEASE</version>
+ <version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -1016,7 +975,7 @@ the Spring BOM
dependencyManagement { (1)
imports {
- mavenBom "org.springframework.cloud:spring-cloud-dependencies:Camden.RELEASE"
+ mavenBom "org.springframework.cloud:spring-cloud-dependencies:Brixton.RELEASE"
}
}
@@ -1050,7 +1009,7 @@ the Spring BOM
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
- <version>Camden.RELEASE</version>
+ <version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -1079,7 +1038,7 @@ the Spring BOM
dependencyManagement { (1)
imports {
- mavenBom "org.springframework.cloud:spring-cloud-dependencies:Camden.RELEASE"
+ mavenBom "org.springframework.cloud:spring-cloud-dependencies:Brixton.RELEASE"
}
}
@@ -1113,7 +1072,7 @@ the Spring BOM
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
- <version>Camden.RELEASE</version>
+ <version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -1157,7 +1116,7 @@ the Spring BOM
dependencyManagement { (1)
imports {
- mavenBom "org.springframework.cloud:spring-cloud-dependencies:Camden.RELEASE"
+ mavenBom "org.springframework.cloud:spring-cloud-dependencies:Brixton.RELEASE"
}
}
@@ -1201,7 +1160,7 @@ dependency
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
- <version>Camden.RELEASE</version>
+ <version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -1245,7 +1204,7 @@ the Spring BOM
dependencyManagement { (1)
imports {
- mavenBom "org.springframework.cloud:spring-cloud-dependencies:Camden.RELEASE"
+ mavenBom "org.springframework.cloud:spring-cloud-dependencies:Brixton.RELEASE"
}
}
@@ -1299,22 +1258,6 @@ public class ZipkinStreamServerApplication {
-Additional resources
-
-
-Marcin Grzejszczak talking about Spring Cloud Sleuth and Zipkin
-
-
-
-
-
-
-
-
-
-
Features
@@ -1384,10 +1327,6 @@ works via Zipkin-compatible request headers. This propagation logic is defined a
SpanInjector and SpanExtractor implementations.
-Sleuth gives you the possibility to propagate context (also known as baggage) between processes. That means that if you set on a Span
-a baggage element then it will be sent downstream either via HTTP or messaging to other processes.
-
-
Provides simple metrics of accepted / dropped spans.
@@ -1752,7 +1691,7 @@ artificial like:
@SpanName annotation
-You can name the span explicitly via the @SpanName annotation.
+You can do name the span explicitly via the @SpanName annotation.
@@ -1837,54 +1776,46 @@ are created and propagated.
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.
-
-The key change in comparison to the previous versions of Sleuth is that Sleuth is implementing
-the Open Tracing’s TextMap notion. In Sleuth it’s called SpanTextMap. Basically the idea
-is that any means of communication (e.g. message, http request, etc.) can be abstracted via
-a SpanTextMap. 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 FooRequest as a mean of sending HTTP requests then you have to create an
-implementation of a SpanTextMap that delegates calls to FooRequest in terms of retrieval
-and insertion of HTTP headers.
-
Spring Integration
-For Spring Integration there are 2 interfaces responsible for creation of a Span from a Message.
-These are:
+For Spring Integration these are the beans responsible for creation of a Span from a Message
+ and filling in the MessageBuilder with tracing information.
+
+
+
+@Bean
+public SpanExtractor<Message> messagingSpanExtractor() {
+ ...
+}
+
+@Bean
+public SpanInjector<MessageBuilder> messagingSpanInjector() {
+ ...
+}
-
-
--
-
MessagingSpanTextMapExtractor
-
--
-
MessagingSpanTextMapInjector
-
-
-You can override them by providing your own implementation.
+You can override them by providing your own implementation and by adding a @Primary annotation
+to your bean definition.
HTTP
-For HTTP there are 2 interfaces responsible for creation of a Span from a Message.
-These are:
+For HTTP these are the beans responsible for creation of a Span from a HttpServletRequest.
+
+
+
+@Bean
+public SpanExtractor<HttpServletRequest> httpServletRequestSpanExtractor() {
+ ...
+}
-
-
--
-
HttpSpanExtractor
-
--
-
HttpSpanInjector
-
-
-You can override them by providing your own implementation.
+You can override them by providing your own implementation and by adding a @Primary annotation
+to your bean definition.
@@ -1908,26 +1839,18 @@ you have
-static class CustomHttpSpanExtractor implements HttpSpanExtractor {
+static class CustomHttpServletRequestSpanExtractor
+ implements SpanExtractor<HttpServletRequest> {
- @Override public Span joinTrace(SpanTextMap carrier) {
- Map<String, String> map = TextMapUtil.asMap(carrier);
- long traceId = Span.hexToId(map.get("correlationid"));
- long spanId = Span.hexToId(map.get("myspanid"));
+ @Override
+ public Span joinTrace(HttpServletRequest carrier) {
+ long traceId = Span.hexToId(carrier.getHeader("correlationId"));
+ long spanId = Span.hexToId(carrier.getHeader("mySpanId"));
// extract all necessary headers
Span.SpanBuilder builder = Span.builder().traceId(traceId).spanId(spanId);
// build rest of the Span
return builder.build();
}
-}
-
-static class CustomHttpSpanInjector implements HttpSpanInjector {
-
- @Override
- public void inject(Span span, SpanTextMap carrier) {
- carrier.put("correlationId", span.traceIdString());
- carrier.put("mySpanId", Span.idToHex(span.getSpanId()));
- }
}
@@ -1937,13 +1860,9 @@ static class CustomHttpSpanInjector implements HttpSpanInjector {
@Bean
-HttpSpanInjector customHttpSpanInjector() {
- return new CustomHttpSpanInjector();
-}
-
-@Bean
-HttpSpanExtractor customHttpSpanExtractor() {
- return new CustomHttpSpanExtractor();
+@Primary
+SpanExtractor<HttpServletRequest> customHttpServletRequestSpanExtractor() {
+ return new CustomHttpServletRequestSpanExtractor();
}
@@ -1953,22 +1872,22 @@ that injects the headers into the Http Response and a Servlet filter which makes
-static class CustomHttpServletResponseSpanInjector extends ZipkinHttpSpanInjector {
+static class CustomHttpServletResponseSpanInjector
+ implements SpanInjector<HttpServletResponse> {
@Override
- public void inject(Span span, SpanTextMap carrier) {
- super.inject(span, carrier);
- carrier.put(Span.TRACE_ID_NAME, span.traceIdString());
- carrier.put(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
+ public void inject(Span span, HttpServletResponse carrier) {
+ carrier.addHeader(Span.TRACE_ID_NAME, span.traceIdString());
+ carrier.addHeader(Span.SPAN_ID_NAME, Span.idToHex(span.getSpanId()));
}
}
static class HttpResponseInjectingTraceFilter extends GenericFilterBean {
private final Tracer tracer;
- private final HttpSpanInjector spanInjector;
+ private final SpanInjector<HttpServletResponse> spanInjector;
- public HttpResponseInjectingTraceFilter(Tracer tracer, HttpSpanInjector spanInjector) {
+ public HttpResponseInjectingTraceFilter(Tracer tracer, SpanInjector<HttpServletResponse> spanInjector) {
this.tracer = tracer;
this.spanInjector = spanInjector;
}
@@ -1977,32 +1896,9 @@ static class HttpResponseInjectingTraceFilter extends GenericFilterBean {
public void doFilter(ServletRequest request, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
Span currentSpan = this.tracer.getCurrentSpan();
- this.spanInjector.inject(currentSpan, new HttpServletResponseTextMap(response));
+ this.spanInjector.inject(currentSpan, response);
filterChain.doFilter(request, response);
}
-
- class HttpServletResponseTextMap implements SpanTextMap {
-
- private final HttpServletResponse delegate;
-
- HttpServletResponseTextMap(HttpServletResponse delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public Iterator<Map.Entry<String, String>> iterator() {
- Map<String, String> map = new HashMap<>();
- for (String header : this.delegate.getHeaderNames()) {
- map.put(header, this.delegate.getHeader(header));
- }
- return map.entrySet().iterator();
- }
-
- @Override
- public void put(String key, String value) {
- this.delegate.addHeader(key, value);
- }
- }
}
@@ -2011,7 +1907,8 @@ static class HttpResponseInjectingTraceFilter extends GenericFilterBean {
-@Bean HttpSpanInjector customHttpServletResponseSpanInjector() {
+@Bean
+SpanInjector<HttpServletResponse> customHttpServletResponseSpanInjector() {
return new CustomHttpServletResponseSpanInjector();
}
@@ -2186,25 +2083,6 @@ the consumer app).
-
-In order to customize the polling mechanism you can create a bean of PollerMetadata type
-with name equal to StreamSpanReporter.POLLER. Here you can find an example of such a configuration.
-
-
-
-@Configuration
-public static class CustomPollerConfiguration {
-
- @Bean(name = StreamSpanReporter.POLLER)
- PollerMetadata customPoller() {
- PollerMetadata poller = new PollerMetadata();
- poller.setMaxMessagesPerPoll(500);
- poller.setTrigger(new PeriodicTrigger(5000L));
- return poller;
- }
-}
-
-
@@ -2513,23 +2391,10 @@ backwards compatibility in 1.0.4 we’ve started sending both valid and inva
in Spring Cloud Sleuth 1.1 we will remove the support for the deprecated headers.
-You can provide the spring.sleuth.integration.patterns pattern to explicitly
+
Since 1.0.4 you can provide the spring.sleuth.integration.patterns pattern to explicitly
provide the names of channels that you want to include for tracing. By default all channels
are included.
-
-
-
-
-Important
-
-
-When using the Executor to build a Spring Integration IntegrationFlow remember to use the untraced version of the Executor.
-Decorating Spring Integration Executor Channel with TraceableExecutorService will cause the spans to be improperly closed.
-
-
-
-
Zuul