From 502749f21a334b9874644b25e524ad4d72edd072 Mon Sep 17 00:00:00 2001 From: buildmaster Date: Fri, 15 Jun 2018 10:56:01 +0000 Subject: [PATCH] Sync docs from master to gh-pages --- multi/multi__additional_resources.html | 3 +- multi/multi__current_span.html | 12 +- multi/multi__features.html | 25 ++-- multi/multi__integrations.html | 3 +- multi/multi__introduction.html | 19 ++- multi/multi__propagation.html | 17 ++- multi/multi__running_examples.html | 5 +- multi/multi__sampling.html | 10 +- multi/multi__zipkin_stream_span_consumer.html | 3 +- multi/multi_spring-cloud-sleuth.html | 2 +- single/spring-cloud-sleuth.html | 99 +++++++++++----- spring-cloud-sleuth.xml | 110 +++++++++++++----- 12 files changed, 221 insertions(+), 87 deletions(-) diff --git a/multi/multi__additional_resources.html b/multi/multi__additional_resources.html index ec3f1930c..244fa2c6d 100644 --- a/multi/multi__additional_resources.html +++ b/multi/multi__additional_resources.html @@ -1,3 +1,4 @@ - 2. Additional Resources

2. Additional Resources

You can watch a video of Marcin Grzejszczak talking about Spring Cloud Sleuth and Zipkin:

click here to see the video

\ No newline at end of file + 2. Additional Resources

2. Additional Resources

You can watch a video of Reshmi Krishna and Marcin Grzejszczak talking about Spring Cloud +Sleuth and Zipkin by clicking here.

You can check different setups of Sleuth and Brave in the openzipkin/sleuth-webmvc-example repository.

\ No newline at end of file diff --git a/multi/multi__current_span.html b/multi/multi__current_span.html index f5c500ef8..6df2346f9 100644 --- a/multi/multi__current_span.html +++ b/multi/multi__current_span.html @@ -1,15 +1,19 @@ 7. Current Span

7. Current Span

Brave supports a "current span" concept which represents the in-flight operation. -You can use Tracer.currentSpan() to add custom tags to a span and Tracer.nextSpan() to create a child of whatever is in-flight.

In Sleuth, you can autowire the Tracer bean to retrieve the current span via +You can use Tracer.currentSpan() to add custom tags to a span and Tracer.nextSpan() to create a child of whatever is in-flight.

[Important]Important

In Sleuth, you can autowire the Tracer bean to retrieve the current span via tracer.currentSpan() method. To retrieve the current context just call tracer.currentSpan().context(). To get the current trace id as String -you can use the traceIdString() method like this: tracer.currentSpan().context().traceIdString().

7.1 Setting a span in scope manually

When writing new instrumentation, it is important to place a span you created in scope as the current span. +you can use the traceIdString() method like this: tracer.currentSpan().context().traceIdString().

7.1 Setting a span in scope manually

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

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

try (SpanInScope ws = tracer.withSpanInScope(span)) {
+Whenever external code might be invoked (such as proceeding an interceptor or otherwise), place the span in scope, as shown in the following example:

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

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

try (SpanInScope cleared = tracer.withSpanInScope(null)) {
+}

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

@Autowired Tracer tracer;
+
+try (SpanInScope cleared = tracer.withSpanInScope(null)) {
   startBackgroundThread();
 }
\ No newline at end of file diff --git a/multi/multi__features.html b/multi/multi__features.html index f21c5840b..bb44cbe90 100644 --- a/multi/multi__features.html +++ b/multi/multi__features.html @@ -42,14 +42,18 @@ It also includes libraries to propagate the trace context over network boundarie Your names have to be explicit and concrete. Big names lead to latency issues and sometimes even thrown exceptions.

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

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

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

3.1.2 Local Tracing

When tracing local code, you can run it inside a span, as shown in the following example:

Span span = tracer.newTrace().name("encode").start();
+After starting a span, you can annotate events of interest or add tags containing details or lookup keys.

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

3.1.2 Local Tracing

When tracing local code, you can run it inside a span, as shown in the following example:

@Autowired Tracer tracer;
+
+Span span = tracer.newTrace().name("encode").start();
 try {
   doSomethingExpensive();
 } finally {
   span.finish();
 }

In the preceding example, the span is the root of the trace. In many cases, the span is part of an existing trace. -When this is the case, call newChild instead of newTrace, as shown in the following example:

Span span = tracer.newChild(root.context()).name("encode").start();
+When this is the case, call newChild instead of newTrace, as shown in the following example:

@Autowired Tracer tracer;
+
+Span span = tracer.newChild(root.context()).name("encode").start();
 try {
   doSomethingExpensive();
 } finally {
@@ -63,12 +67,14 @@ The former is simpler to understand and test and does not tempt users with span
   callback.request(request, span);
 }

3.1.4 Implicitly Looking up the Current Span

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

Ex.

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

3.1.5 RPC tracing

[Tip]Tip

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

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

The following example shows how to add a client span:

// before you send a request, add metadata that describes the operation
+}

3.1.5 RPC tracing

[Tip]Tip

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

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

The following example shows how to add a client span:

@Autowired Tracer tracer;
+
+// before you send a request, add metadata that describes the operation
 span = tracer.newTrace().name("get").type(CLIENT);
 span.tag("clnt/finagle.version", "6.36.0");
 span.tag(TraceKeys.HTTP_PATH, "/api");
@@ -88,7 +94,9 @@ span.annotate(Constants.WIRE_RECV);
 span.finish();

One-Way tracing

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

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

// start a new span representing a client request
+span.flush() instead, as you do not expect a response.

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

@Autowired Tracer tracer;
+
+// start a new span representing a client request
 oneWaySend = tracer.newSpan(parent).kind(Span.Kind.CLIENT);
 
 // Add the trace context to the request, so it can be propagated in-band
@@ -99,7 +107,10 @@ tracing.propagation().injector(Request::addHeader)
 request.execute();
 
 // start the client side and flush instead of finish
-oneWaySend.start().flush();

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

// pull the context out of the incoming request
+oneWaySend.start().flush();

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

@Autowired Tracing tracing;
+@Autowired Tracer tracer;
+
+// pull the context out of the incoming request
 extractor = tracing.propagation().extractor(Request::getHeader);
 
 // convert that context to a span which you can name and add tags to
@@ -113,4 +124,4 @@ oneWayReceive.start().flush();
 
 // you should not modify this span anymore as it is complete. However,
 // you can create children to represent follow-up work.
-next = tracer.newSpan(oneWayReceive.context()).name("step2").start();
[Note]Note

The propagation logic shown in the preceding example is a simplified version of our http handlers.

\ No newline at end of file +next = tracer.newSpan(oneWayReceive.context()).name("step2").start(); \ No newline at end of file diff --git a/multi/multi__integrations.html b/multi/multi__integrations.html index f5eb96997..aa2def57b 100644 --- a/multi/multi__integrations.html +++ b/multi/multi__integrations.html @@ -151,5 +151,6 @@ By default, all channels but hystrixStreamOutput ch Decorating the Spring Integration Executor Channel with TraceableExecutorService causes the spans to be improperly closed.

15.9.2 Spring RabbitMq

We instrument the RabbitTemplate so that tracing headers get injected into the message.

To block this feature, set spring.sleuth.messaging.rabbit.enabled to false.

15.9.3 Spring Kafka

We instrument the Spring Kafka’s ProducerFactory and ConsumerFactory so that tracing headers get injected into the created Spring Kafka’s -Producer and Consumer.

To block this feature, set spring.sleuth.messaging.kafka.enabled to false.

15.10 Zuul

We instrument the Zuul Ribbon integration by enriching the Ribbon requests with tracing information. +Producer and Consumer.

To block this feature, set spring.sleuth.messaging.kafka.enabled to false.

[Note]Note

We do not support context propagation via @KafkaListener annotation. +Check this issue for more information.

15.10 Zuul

We instrument the Zuul Ribbon integration by enriching the Ribbon requests with tracing information. To disable Zuul support, set the spring.sleuth.zuul.enabled property to false.

\ No newline at end of file diff --git a/multi/multi__introduction.html b/multi/multi__introduction.html index 7bfd00fb5..6567cbe6e 100644 --- a/multi/multi__introduction.html +++ b/multi/multi__introduction.html @@ -17,7 +17,7 @@ The client has successfully received the response from the server side. Subtracting the cs timestamp from this timestamp reveals the whole time needed by the client to receive the response from the server.

The following image shows how Span and Trace look in a system, together with the Zipkin annotations:

Trace Info propagation

Each color of a note signifies a span (there are seven spans - from A to G). Consider the following note:

Trace Id = X
 Span Id = D
-Client Sent

This note indicats thatthe current span has Trace Id set to X and Span Id set to D. +Client Sent

This note indicates that the current span has Trace Id set to X and Span Id set to D. Also, the Client Sent event took place.

The following image shows how parent-child relationships of spans look:

Parent child relationship

1.2 Purpose

The following sections refer to the example shown in the preceding image.

1.2.1 Distributed Tracing with Zipkin

This example has seven spans. If you go to traces in Zipkin, you can see this number in the second trace, as shown in the following image:

Traces

However, if you pick a particular trace, you can see four spans, as shown in the following image:

Traces Info propagation
[Note]Note

When you pick a particular trace, you see merged spans. That means that, if there were two spans sent to Zipkin with Server Received and Server Sent or Client Received and Client Sent annotations, they are presented as a single span.

Why is there a difference between the seven and four spans in this case?

  • Two spans come from the http:/start span. It has the Server Received (sr) and Server Sent (ss) annotations.
  • Two spans come from the RPC call from service1 to service2 to the http:/foo endpoint. @@ -140,11 +140,22 @@ In extreme cases, too much baggage can crash the application, due to exceeding t ExtraFieldPropagation.set("foo", "bar"); ExtraFieldPropagation.set("UPPER_CASE", "someValue"); }

    Baggage versus Span Tags

    Baggage travels with the trace (every child span contains the baggage of its parent). -Zipkin has no knowledge of baggage and does not receive that information.

    Tags are attached to a specific span. In other words, they are presented only for that particular span. -However, you can search by tag to find the trace, assuming a span having the searched tag value exists.

    If you want to be able to lookup a span based on baggage, you should add a corresponding entry as a tag in the root span.

    [Important]Important

    The span must be in scope.

    The following listing shows integration tests that use baggage:

    initialSpan.tag("foo",
    +Zipkin has no knowledge of baggage and does not receive that information.

    [Important]Important

    Starting from Sleuth 2.0.0 you have to pass the baggage key names explicitly +in your project configuration. Read more about that setup here

    Tags are attached to a specific span. In other words, they are presented only for that particular span. +However, you can search by tag to find the trace, assuming a span having the searched tag value exists.

    If you want to be able to lookup a span based on baggage, you should add a corresponding entry as a tag in the root span.

    [Important]Important

    The span must be in scope.

    The following listing shows integration tests that use baggage:

    The setup.  +

    spring.sleuth:
    +  baggage-keys:
    +    - baz
    +    - bizarrecase
    +  propagation-keys:
    +    - foo
    +    - upper_case

    +

    The code.  +

    initialSpan.tag("foo",
     		ExtraFieldPropagation.get(initialSpan.context(), "foo"));
     initialSpan.tag("UPPER_CASE",
    -		ExtraFieldPropagation.get(initialSpan.context(), "UPPER_CASE"));

1.3 Adding Sleuth to the Project

This section addresses how to add Sleuth to your project with either Maven or Gradle.

[Important]Important

To ensure that your application name is properly displayed in Zipkin, set the spring.application.name property in bootstrap.yml.

1.3.1 Only Sleuth (log correlation)

If you want to use only Spring Cloud Sleuth without the Zipkin integration, add the spring-cloud-starter-sleuth module to your project.

The following example shows how to add Sleuth with Maven:

Maven.  + ExtraFieldPropagation.get(initialSpan.context(), "UPPER_CASE"));

+

1.3 Adding Sleuth to the Project

This section addresses how to add Sleuth to your project with either Maven or Gradle.

[Important]Important

To ensure that your application name is properly displayed in Zipkin, set the spring.application.name property in bootstrap.yml.

1.3.1 Only Sleuth (log correlation)

If you want to use only Spring Cloud Sleuth without the Zipkin integration, add the spring-cloud-starter-sleuth module to your project.

The following example shows how to add Sleuth with Maven:

Maven. 

<dependencyManagement> 1
       <dependencies>
           <dependency>
diff --git a/multi/multi__propagation.html b/multi/multi__propagation.html
index 8d40e24d1..e00d22cfc 100644
--- a/multi/multi__propagation.html
+++ b/multi/multi__propagation.html
@@ -16,17 +16,22 @@ The most common propagation approach is to copy a trace context from a client by
 │ └──────────────┘ │          └───────────────────┘        │ └──────────────┘ │
 │                  │                                       │                  │
 └──────────────────┘                                       └──────────────────┘

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

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

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

// configure a function that injects a trace context into a request
+The next two examples show how that might work for a client and a server.

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

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

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

// configure a function that extracts the trace context from a request
+injector.inject(span.context(), request);

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

@Autowired Tracing tracing;
+@Autowired Tracer tracer;
+
+// configure a function that extracts the trace context from a request
 extractor = tracing.propagation().extractor(Request::getHeader);
 
 // when a server receives a request, it joins or starts a new trace
 span = tracer.nextSpan(extractor.extract(request));

5.1 Propagating extra fields

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, as shown in the following example:

// when you initialize the builder, define the extra field you want to propagate
-tracingBuilder.propagationFactory(
+Tracing.newBuilder().propagationFactory(
   ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "x-vcap-request-id")
 );
 
@@ -35,8 +40,10 @@ requestId = ExtraFieldPropagation.get(tracingBuilder.propagationFactory(
   ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "x-amzn-trace-id")
-);

5.1.1 Prefixed fields

If they follow a common pattern, you can also prefix fields. -The following example shows how to propagate x-vcap-request-id the field as-is but send the country-code and user-id fields on the wire as x-baggage-country-code and x-baggage-user-id, respectively:

tracingBuilder.propagationFactory(
+);
[Tip]Tip

In Spring Cloud Sleuth all elements of the tracing builder Tracing.newBuilder() +are defined as beans. So if you want to pass a custom PropagationFactory, it’s enough +for you to create a bean of that type and we will set it in the Tracing bean.

5.1.1 Prefixed fields

If they follow a common pattern, you can also prefix fields. +The following example shows how to propagate x-vcap-request-id the field as-is but send the country-code and user-id fields on the wire as x-baggage-country-code and x-baggage-user-id, respectively:

Tracing.newBuilder().propagationFactory(
   ExtraFieldPropagation.newFactoryBuilder(B3Propagation.FACTORY)
                        .addField("x-vcap-request-id")
                        .addPrefixedFields("baggage-", Arrays.asList("country-code", "user-id"))
diff --git a/multi/multi__running_examples.html b/multi/multi__running_examples.html
index 11eef5273..6da03204d 100644
--- a/multi/multi__running_examples.html
+++ b/multi/multi__running_examples.html
@@ -1,4 +1,7 @@
 
       
    16. Running examples

16. Running examples

You can see the running examples deployed in the Pivotal Web Services. -Check them out at the following links:

\ No newline at end of file +Check them out at the following links:

\ No newline at end of file diff --git a/multi/multi__sampling.html b/multi/multi__sampling.html index 05af42729..115979dc0 100644 --- a/multi/multi__sampling.html +++ b/multi/multi__sampling.html @@ -3,7 +3,9 @@ 4. Sampling

4. Sampling

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

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

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

4.1 Declarative sampling

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

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

// derives a sample rate from an annotation on a java method
+The following example shows how that might work internally:

@Autowired Tracing tracing;
+
+// derives a sample rate from an annotation on a java method
 DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sampleRate);
 
 @Around("@annotation(traced)")
@@ -16,7 +18,9 @@ DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sam
   }
 }

4.2 Custom sampling

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

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

Span newTrace(Request input) {
+The following example shows how that might work internally:

@Autowired Tracer tracer;
+
+Span newTrace(Request input) {
   SamplingFlags flags = SamplingFlags.NONE;
   if (input.url().startsWith("/experimental")) {
     flags = SamplingFlags.SAMPLED;
@@ -24,7 +28,7 @@ The following example shows how that might work internally:

return tracer.newTrace(flags);
-}
[Note]Note

The preceding example forms the basis for the built-in http sampler.

4.3 Sampling in Spring Cloud Sleuth

By default Spring Cloud Sleuth sets all spans to non-exportable. +}

4.3 Sampling in Spring Cloud Sleuth

By default Spring Cloud Sleuth sets all spans to non-exportable. That means that traces appear in logs but not in any remote store. For testing the default is often enough, and it probably is all you need if you use only the logs (for example, with an ELK aggregator). If you export span data to Zipkin, there is also an Sampler.ALWAYS_SAMPLE setting that exports everything and a ProbabilityBasedSampler setting that samples a fixed fraction of spans.

[Note]Note

The ProbabilityBasedSampler is the default if you use spring-cloud-sleuth-zipkin. diff --git a/multi/multi__zipkin_stream_span_consumer.html b/multi/multi__zipkin_stream_span_consumer.html index 527157b4c..6570accf0 100644 --- a/multi/multi__zipkin_stream_span_consumer.html +++ b/multi/multi__zipkin_stream_span_consumer.html @@ -2,5 +2,4 @@ 14. Zipkin Stream Span Consumer

14. Zipkin Stream Span Consumer

[Important]Important

We recommend using Zipkin’s native support for message-based span sending. Starting from the Edgware release, the Zipkin Stream server is deprecated. -In the Finchley release, it got removed.

See the Dalston Documentation -for how to create a Stream Zipkin server.

\ No newline at end of file +In the Finchley release, it got removed.

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

\ No newline at end of file diff --git a/multi/multi_spring-cloud-sleuth.html b/multi/multi_spring-cloud-sleuth.html index 52fc0ce7e..f52ccbb79 100644 --- a/multi/multi_spring-cloud-sleuth.html +++ b/multi/multi_spring-cloud-sleuth.html @@ -1,3 +1,3 @@ - Spring Cloud Sleuth

Spring Cloud Sleuth

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

Table of Contents

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

Spring Cloud Sleuth

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

Table of Contents

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

Spring Cloud Sleuth

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

Table of Contents

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

2.0.0.BUILD-SNAPSHOT

1. Introduction

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

1.1 Terminology

Spring Cloud Sleuth borrows Dapper’s terminology.

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

Spring Cloud Sleuth

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

Table of Contents

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

2.0.0.BUILD-SNAPSHOT

1. Introduction

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

1.1 Terminology

Spring Cloud Sleuth borrows Dapper’s terminology.

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

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

[Tip]Tip

The initial span that starts a trace is called a root span. The value of the ID @@ -17,7 +17,7 @@ The client has successfully received the response from the server side. Subtracting the cs timestamp from this timestamp reveals the whole time needed by the client to receive the response from the server.

The following image shows how Span and Trace look in a system, together with the Zipkin annotations:

Trace Info propagation

Each color of a note signifies a span (there are seven spans - from A to G). Consider the following note:

Trace Id = X
 Span Id = D
-Client Sent

This note indicats thatthe current span has Trace Id set to X and Span Id set to D. +Client Sent

This note indicates that the current span has Trace Id set to X and Span Id set to D. Also, the Client Sent event took place.

The following image shows how parent-child relationships of spans look:

Parent child relationship

1.2 Purpose

The following sections refer to the example shown in the preceding image.

1.2.1 Distributed Tracing with Zipkin

This example has seven spans. If you go to traces in Zipkin, you can see this number in the second trace, as shown in the following image:

Traces

However, if you pick a particular trace, you can see four spans, as shown in the following image:

Traces Info propagation
[Note]Note

When you pick a particular trace, you see merged spans. That means that, if there were two spans sent to Zipkin with Server Received and Server Sent or Client Received and Client Sent annotations, they are presented as a single span.

Why is there a difference between the seven and four spans in this case?

  • Two spans come from the http:/start span. It has the Server Received (sr) and Server Sent (ss) annotations.
  • Two spans come from the RPC call from service1 to service2 to the http:/foo endpoint. @@ -140,11 +140,22 @@ In extreme cases, too much baggage can crash the application, due to exceeding t ExtraFieldPropagation.set("foo", "bar"); ExtraFieldPropagation.set("UPPER_CASE", "someValue"); }

    Baggage versus Span Tags

    Baggage travels with the trace (every child span contains the baggage of its parent). -Zipkin has no knowledge of baggage and does not receive that information.

    Tags are attached to a specific span. In other words, they are presented only for that particular span. -However, you can search by tag to find the trace, assuming a span having the searched tag value exists.

    If you want to be able to lookup a span based on baggage, you should add a corresponding entry as a tag in the root span.

    [Important]Important

    The span must be in scope.

    The following listing shows integration tests that use baggage:

    initialSpan.tag("foo",
    +Zipkin has no knowledge of baggage and does not receive that information.

    [Important]Important

    Starting from Sleuth 2.0.0 you have to pass the baggage key names explicitly +in your project configuration. Read more about that setup here

    Tags are attached to a specific span. In other words, they are presented only for that particular span. +However, you can search by tag to find the trace, assuming a span having the searched tag value exists.

    If you want to be able to lookup a span based on baggage, you should add a corresponding entry as a tag in the root span.

    [Important]Important

    The span must be in scope.

    The following listing shows integration tests that use baggage:

    The setup.  +

    spring.sleuth:
    +  baggage-keys:
    +    - baz
    +    - bizarrecase
    +  propagation-keys:
    +    - foo
    +    - upper_case

    +

    The code.  +

    initialSpan.tag("foo",
     		ExtraFieldPropagation.get(initialSpan.context(), "foo"));
     initialSpan.tag("UPPER_CASE",
    -		ExtraFieldPropagation.get(initialSpan.context(), "UPPER_CASE"));

1.3 Adding Sleuth to the Project

This section addresses how to add Sleuth to your project with either Maven or Gradle.

[Important]Important

To ensure that your application name is properly displayed in Zipkin, set the spring.application.name property in bootstrap.yml.

1.3.1 Only Sleuth (log correlation)

If you want to use only Spring Cloud Sleuth without the Zipkin integration, add the spring-cloud-starter-sleuth module to your project.

The following example shows how to add Sleuth with Maven:

Maven.  + ExtraFieldPropagation.get(initialSpan.context(), "UPPER_CASE"));

+

1.3 Adding Sleuth to the Project

This section addresses how to add Sleuth to your project with either Maven or Gradle.

[Important]Important

To ensure that your application name is properly displayed in Zipkin, set the spring.application.name property in bootstrap.yml.

1.3.1 Only Sleuth (log correlation)

If you want to use only Spring Cloud Sleuth without the Zipkin integration, add the spring-cloud-starter-sleuth module to your project.

The following example shows how to add Sleuth with Maven:

Maven. 

<dependencyManagement> 1
       <dependencies>
           <dependency>
@@ -232,7 +243,8 @@ dependencies {
     compile "org.springframework.cloud:spring-cloud-starter-zipkin" 2
     compile "org.springframework.amqp:spring-rabbit" 3
 }

-

1

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

2

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

3

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

2. Additional Resources

You can watch a video of Marcin Grzejszczak talking about Spring Cloud Sleuth and Zipkin:

click here to see the video

3. Features

  • Adds trace and span IDs to the Slf4J MDC, so you can extract all the logs from a given trace or span in a log aggregator, as shown in the following example logs:

    2016-02-02 15:30:57.902  INFO [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ...
    +

    1

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

    2

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

    3

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

2. Additional Resources

You can watch a video of Reshmi Krishna and Marcin Grzejszczak talking about Spring Cloud +Sleuth and Zipkin by clicking here.

You can check different setups of Sleuth and Brave in the openzipkin/sleuth-webmvc-example repository.

3. Features

  • Adds trace and span IDs to the Slf4J MDC, so you can extract all the logs from a given trace or span in a log aggregator, as shown in the following example logs:

    2016-02-02 15:30:57.902  INFO [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ...
     2016-02-02 15:30:58.372 ERROR [bar,6bfd228dc00d216b,6bfd228dc00d216b,false] 23030 --- [nio-8081-exec-3] ...
     2016-02-02 15:31:01.936  INFO [bar,46ab0d418373cbc9,46ab0d418373cbc9,false] 23030 --- [nio-8081-exec-4] ...

    Notice the [appname,traceId,spanId,exportable] entries from the MDC:

    • spanId: The ID of a specific operation that took place.
    • appname: The name of the application that logged the span.
    • traceId: The ID of the latency graph that contains the span.
    • exportable: Whether the log should be exported to Zipkin. When would you like the span not to be exportable? @@ -274,14 +286,18 @@ It also includes libraries to propagate the trace context over network boundarie Your names have to be explicit and concrete. Big names lead to latency issues and sometimes even thrown exceptions.

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

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

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

3.1.2 Local Tracing

When tracing local code, you can run it inside a span, as shown in the following example:

Span span = tracer.newTrace().name("encode").start();
+After starting a span, you can annotate events of interest or add tags containing details or lookup keys.

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

3.1.2 Local Tracing

When tracing local code, you can run it inside a span, as shown in the following example:

@Autowired Tracer tracer;
+
+Span span = tracer.newTrace().name("encode").start();
 try {
   doSomethingExpensive();
 } finally {
   span.finish();
 }

In the preceding example, the span is the root of the trace. In many cases, the span is part of an existing trace. -When this is the case, call newChild instead of newTrace, as shown in the following example:

Span span = tracer.newChild(root.context()).name("encode").start();
+When this is the case, call newChild instead of newTrace, as shown in the following example:

@Autowired Tracer tracer;
+
+Span span = tracer.newChild(root.context()).name("encode").start();
 try {
   doSomethingExpensive();
 } finally {
@@ -295,12 +311,14 @@ The former is simpler to understand and test and does not tempt users with span
   callback.request(request, span);
 }

3.1.4 Implicitly Looking up the Current Span

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

Ex.

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

3.1.5 RPC tracing

[Tip]Tip

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

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

The following example shows how to add a client span:

// before you send a request, add metadata that describes the operation
+}

3.1.5 RPC tracing

[Tip]Tip

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

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

The following example shows how to add a client span:

@Autowired Tracer tracer;
+
+// before you send a request, add metadata that describes the operation
 span = tracer.newTrace().name("get").type(CLIENT);
 span.tag("clnt/finagle.version", "6.36.0");
 span.tag(TraceKeys.HTTP_PATH, "/api");
@@ -320,7 +338,9 @@ span.annotate(Constants.WIRE_RECV);
 span.finish();

One-Way tracing

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

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

// start a new span representing a client request
+span.flush() instead, as you do not expect a response.

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

@Autowired Tracer tracer;
+
+// start a new span representing a client request
 oneWaySend = tracer.newSpan(parent).kind(Span.Kind.CLIENT);
 
 // Add the trace context to the request, so it can be propagated in-band
@@ -331,7 +351,10 @@ tracing.propagation().injector(Request::addHeader)
 request.execute();
 
 // start the client side and flush instead of finish
-oneWaySend.start().flush();

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

// pull the context out of the incoming request
+oneWaySend.start().flush();

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

@Autowired Tracing tracing;
+@Autowired Tracer tracer;
+
+// pull the context out of the incoming request
 extractor = tracing.propagation().extractor(Request::getHeader);
 
 // convert that context to a span which you can name and add tags to
@@ -345,10 +368,12 @@ oneWayReceive.start().flush();
 
 // you should not modify this span anymore as it is complete. However,
 // you can create children to represent follow-up work.
-next = tracer.newSpan(oneWayReceive.context()).name("step2").start();
[Note]Note

The propagation logic shown in the preceding example is a simplified version of our http handlers.

4. Sampling

Sampling may be employed to reduce the data collected and reported out of process. +next = tracer.newSpan(oneWayReceive.context()).name("step2").start();

4. Sampling

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

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

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

4.1 Declarative sampling

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

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

// derives a sample rate from an annotation on a java method
+The following example shows how that might work internally:

@Autowired Tracing tracing;
+
+// derives a sample rate from an annotation on a java method
 DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sampleRate);
 
 @Around("@annotation(traced)")
@@ -361,7 +386,9 @@ DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sam
   }
 }

4.2 Custom sampling

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

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

Span newTrace(Request input) {
+The following example shows how that might work internally:

@Autowired Tracer tracer;
+
+Span newTrace(Request input) {
   SamplingFlags flags = SamplingFlags.NONE;
   if (input.url().startsWith("/experimental")) {
     flags = SamplingFlags.SAMPLED;
@@ -369,7 +396,7 @@ The following example shows how that might work internally:

return tracer.newTrace(flags);
-}
[Note]Note

The preceding example forms the basis for the built-in http sampler.

4.3 Sampling in Spring Cloud Sleuth

By default Spring Cloud Sleuth sets all spans to non-exportable. +}

4.3 Sampling in Spring Cloud Sleuth

By default Spring Cloud Sleuth sets all spans to non-exportable. That means that traces appear in logs but not in any remote store. For testing the default is often enough, and it probably is all you need if you use only the logs (for example, with an ELK aggregator). If you export span data to Zipkin, there is also an Sampler.ALWAYS_SAMPLE setting that exports everything and a ProbabilityBasedSampler setting that samples a fixed fraction of spans.

[Note]Note

The ProbabilityBasedSampler is the default if you use spring-cloud-sleuth-zipkin. @@ -394,17 +421,22 @@ The most common propagation approach is to copy a trace context from a client by │ └──────────────┘ │ └───────────────────┘ │ └──────────────┘ │ │ │ │ │ └──────────────────┘ └──────────────────┘

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

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

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

// configure a function that injects a trace context into a request
+The next two examples show how that might work for a client and a server.

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

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

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

// configure a function that extracts the trace context from a request
+injector.inject(span.context(), request);

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

@Autowired Tracing tracing;
+@Autowired Tracer tracer;
+
+// configure a function that extracts the trace context from a request
 extractor = tracing.propagation().extractor(Request::getHeader);
 
 // when a server receives a request, it joins or starts a new trace
 span = tracer.nextSpan(extractor.extract(request));

5.1 Propagating extra fields

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, as shown in the following example:

// when you initialize the builder, define the extra field you want to propagate
-tracingBuilder.propagationFactory(
+Tracing.newBuilder().propagationFactory(
   ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "x-vcap-request-id")
 );
 
@@ -413,8 +445,10 @@ requestId = ExtraFieldPropagation.get(tracingBuilder.propagationFactory(
   ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "x-amzn-trace-id")
-);

5.1.1 Prefixed fields

If they follow a common pattern, you can also prefix fields. -The following example shows how to propagate x-vcap-request-id the field as-is but send the country-code and user-id fields on the wire as x-baggage-country-code and x-baggage-user-id, respectively:

tracingBuilder.propagationFactory(
+);
[Tip]Tip

In Spring Cloud Sleuth all elements of the tracing builder Tracing.newBuilder() +are defined as beans. So if you want to pass a custom PropagationFactory, it’s enough +for you to create a bean of that type and we will set it in the Tracing bean.

5.1.1 Prefixed fields

If they follow a common pattern, you can also prefix fields. +The following example shows how to propagate x-vcap-request-id the field as-is but send the country-code and user-id fields on the wire as x-baggage-country-code and x-baggage-user-id, respectively:

Tracing.newBuilder().propagationFactory(
   ExtraFieldPropagation.newFactoryBuilder(B3Propagation.FACTORY)
                        .addField("x-vcap-request-id")
                        .addPrefixedFields("baggage-", Arrays.asList("country-code", "user-id"))
@@ -465,16 +499,20 @@ This was made for JDBC connections, as they often initialize prior to the tracin
 You can also use Tracing.currentTracer() to get only the tracer.
 If you use either of these methods, do not cache the result.
 Instead, look them up each time you need them.

7. Current Span

Brave supports a "current span" concept which represents the in-flight operation. -You can use Tracer.currentSpan() to add custom tags to a span and Tracer.nextSpan() to create a child of whatever is in-flight.

In Sleuth, you can autowire the Tracer bean to retrieve the current span via +You can use Tracer.currentSpan() to add custom tags to a span and Tracer.nextSpan() to create a child of whatever is in-flight.

[Important]Important

In Sleuth, you can autowire the Tracer bean to retrieve the current span via tracer.currentSpan() method. To retrieve the current context just call tracer.currentSpan().context(). To get the current trace id as String -you can use the traceIdString() method like this: tracer.currentSpan().context().traceIdString().

7.1 Setting a span in scope manually

When writing new instrumentation, it is important to place a span you created in scope as the current span. +you can use the traceIdString() method like this: tracer.currentSpan().context().traceIdString().

7.1 Setting a span in scope manually

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

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

try (SpanInScope ws = tracer.withSpanInScope(span)) {
+Whenever external code might be invoked (such as proceeding an interceptor or otherwise), place the span in scope, as shown in the following example:

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

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

try (SpanInScope cleared = tracer.withSpanInScope(null)) {
+}

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

@Autowired Tracer tracer;
+
+try (SpanInScope cleared = tracer.withSpanInScope(null)) {
   startBackgroundThread();
 }

8. Instrumentation

Spring Cloud Sleuth automatically instruments all your Spring applications, so you should not have to do anything to activate it. The instrumentation is added by using a variety of technologies according to the stack that is available. For example, for a servlet web application, we use a Filter, and, for Spring Integration, we use ChannelInterceptors.

You can customize the keys used in span tags. @@ -695,8 +733,7 @@ object, you will have to create a bean of zipkin2.reporter return myCustomSender(zipkin, restTemplate); }

14. Zipkin Stream Span Consumer

[Important]Important

We recommend using Zipkin’s native support for message-based span sending. Starting from the Edgware release, the Zipkin Stream server is deprecated. -In the Finchley release, it got removed.

See the Dalston Documentation -for how to create a Stream Zipkin server.

15. Integrations

15.1 OpenTracing

Spring Cloud Sleuth is compatible with OpenTracing. +In the Finchley release, it got removed.

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

15. Integrations

15.1 OpenTracing

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

15.2 Runnable and Callable

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

Runnable runnable = new Runnable() {
 	@Override
@@ -847,6 +884,10 @@ By default, all channels but hystrixStreamOutput ch
 Decorating the Spring Integration Executor Channel with TraceableExecutorService causes the spans to be improperly closed.

15.9.2 Spring RabbitMq

We instrument the RabbitTemplate so that tracing headers get injected into the message.

To block this feature, set spring.sleuth.messaging.rabbit.enabled to false.

15.9.3 Spring Kafka

We instrument the Spring Kafka’s ProducerFactory and ConsumerFactory so that tracing headers get injected into the created Spring Kafka’s -Producer and Consumer.

To block this feature, set spring.sleuth.messaging.kafka.enabled to false.

15.10 Zuul

We instrument the Zuul Ribbon integration by enriching the Ribbon requests with tracing information. +Producer and Consumer.

To block this feature, set spring.sleuth.messaging.kafka.enabled to false.

[Note]Note

We do not support context propagation via @KafkaListener annotation. +Check this issue for more information.

15.10 Zuul

We instrument the Zuul Ribbon integration by enriching the Ribbon requests with tracing information. To disable Zuul support, set the spring.sleuth.zuul.enabled property to false.

16. Running examples

You can see the running examples deployed in the Pivotal Web Services. -Check them out at the following links:

\ No newline at end of file +Check them out at the following links:

\ No newline at end of file diff --git a/spring-cloud-sleuth.xml b/spring-cloud-sleuth.xml index 65c81d387..3490e50ef 100644 --- a/spring-cloud-sleuth.xml +++ b/spring-cloud-sleuth.xml @@ -71,7 +71,7 @@ Consider the following note: Trace Id = X Span Id = D Client Sent -This note indicats thatthe current span has Trace Id set to X and Span Id set to D. +This note indicates that the current span has Trace Id set to X and Span Id set to D. Also, the Client Sent event took place. The following image shows how parent-child relationships of spans look: @@ -372,6 +372,10 @@ try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initialSpan)) { Baggage versus Span Tags Baggage travels with the trace (every child span contains the baggage of its parent). Zipkin has no knowledge of baggage and does not receive that information. + +Starting from Sleuth 2.0.0 you have to pass the baggage key names explicitly +in your project configuration. Read more about that setup here + Tags are attached to a specific span. In other words, they are presented only for that particular span. However, you can search by tag to find the trace, assuming a span having the searched tag value exists. If you want to be able to lookup a span based on baggage, you should add a corresponding entry as a tag in the root span. @@ -379,10 +383,27 @@ However, you can search by tag to find the trace, assuming a span having the sea The span must be in scope. The following listing shows integration tests that use baggage: + +The setup + +spring.sleuth: + baggage-keys: + - baz + - bizarrecase + propagation-keys: + - foo + - upper_case + + + +The code + initialSpan.tag("foo", ExtraFieldPropagation.get(initialSpan.context(), "foo")); initialSpan.tag("UPPER_CASE", ExtraFieldPropagation.get(initialSpan.context(), "UPPER_CASE")); + + @@ -583,9 +604,9 @@ dependencies { Additional Resources -You can watch a video of Marcin Grzejszczak talking about Spring Cloud Sleuth and Zipkin: - -click here to see the video +You can watch a video of Reshmi Krishna and Marcin Grzejszczak talking about Spring Cloud +Sleuth and Zipkin by clicking here. +You can check different setups of Sleuth and Brave in the openzipkin/sleuth-webmvc-example repository. Features @@ -734,7 +755,9 @@ After starting a span, you can annotate events of interest or add tags containin
Local Tracing When tracing local code, you can run it inside a span, as shown in the following example: -Span span = tracer.newTrace().name("encode").start(); +@Autowired Tracer tracer; + +Span span = tracer.newTrace().name("encode").start(); try { doSomethingExpensive(); } finally { @@ -743,7 +766,9 @@ try { In the preceding example, the span is the root of the trace. In many cases, the span is part of an existing trace. When this is the case, call newChild instead of newTrace, as shown in the following example: -Span span = tracer.newChild(root.context()).name("encode").start(); +@Autowired Tracer tracer; + +Span span = tracer.newChild(root.context()).name("encode").start(); try { doSomethingExpensive(); } finally { @@ -772,7 +797,7 @@ The former is simpler to understand and test and does not tempt users with span brave.CurrentSpanCustomizer handles this problem by adding data to any span that’s in progress or drops, as shown in the following example: Ex. // The user code can then inject this without a chance of it being null. -@Autowire SpanCustomizer span; +@Autowired SpanCustomizer span; void userCode() { span.annotate("tx.started"); @@ -786,7 +811,9 @@ void userCode() { RPC tracing is often done automatically by interceptors. Behind the scenes, they add tags and events that relate to their role in an RPC operation. The following example shows how to add a client span: -// before you send a request, add metadata that describes the operation +@Autowired Tracer tracer; + +// before you send a request, add metadata that describes the operation span = tracer.newTrace().name("get").type(CLIENT); span.tag("clnt/finagle.version", "6.36.0"); span.tag(TraceKeys.HTTP_PATH, "/api"); @@ -811,7 +838,9 @@ request but no response. In normal RPC tracing, you use span.finish()span.flush() instead, as you do not expect a response. The following example shows how a client might model a one-way operation: -// start a new span representing a client request +@Autowired Tracer tracer; + +// start a new span representing a client request oneWaySend = tracer.newSpan(parent).kind(Span.Kind.CLIENT); // Add the trace context to the request, so it can be propagated in-band @@ -824,7 +853,10 @@ request.execute(); // start the client side and flush instead of finish oneWaySend.start().flush(); The following example shows how a server might handle a one-way operation: -// pull the context out of the incoming request +@Autowired Tracing tracing; +@Autowired Tracer tracer; + +// pull the context out of the incoming request extractor = tracing.propagation().extractor(Request::getHeader); // convert that context to a span which you can name and add tags to @@ -839,9 +871,6 @@ oneWayReceive.start().flush(); // you should not modify this span anymore as it is complete. However, // you can create children to represent follow-up work. next = tracer.newSpan(oneWayReceive.context()).name("step2").start(); - -The propagation logic shown in the preceding example is a simplified version of our http handlers. -
@@ -858,7 +887,9 @@ When a span is not sampled, it adds no overhead (a noop).
Some applications need to sample based on the type or annotations of a java method. Most users use a framework interceptor to automate this sort of policy. The following example shows how that might work internally: -// derives a sample rate from an annotation on a java method +@Autowired Tracing tracing; + +// derives a sample rate from an annotation on a java method DeclarativeSampler<Traced> sampler = DeclarativeSampler.create(Traced::sampleRate); @Around("@annotation(traced)") @@ -877,7 +908,9 @@ public Object traceThing(ProceedingJoinPoint pjp, Traced traced) throws Throwabl For example, you might not want to trace requests to static resources such as images, or you might want to trace all requests to a new api. Most users use a framework interceptor to automate this sort of policy. The following example shows how that might work internally: -Span newTrace(Request input) { +@Autowired Tracer tracer; + +Span newTrace(Request input) { SamplingFlags flags = SamplingFlags.NONE; if (input.url().startsWith("/experimental")) { flags = SamplingFlags.SAMPLED; @@ -886,9 +919,6 @@ The following example shows how that might work internally: } return tracer.newTrace(flags); } - -The preceding example forms the basis for the built-in http sampler. -
Sampling in Spring Cloud Sleuth @@ -936,13 +966,18 @@ The most common propagation approach is to copy a trace context from a client by Most users use a framework interceptor to automate propagation. The next two examples show how that might work for a client and a server. The following example shows how client-side propagation might work: -// configure a function that injects a trace context into a request +@Autowired Tracing tracing; + +// configure a function that injects a trace context into a request injector = tracing.propagation().injector(Request.Builder::addHeader); // before a request is sent, add the current span's context to it injector.inject(span.context(), request); The following example shows how server-side propagation might work: -// configure a function that extracts the trace context from a request +@Autowired Tracing tracing; +@Autowired Tracer tracer; + +// configure a function that extracts the trace context from a request extractor = tracing.propagation().extractor(Request::getHeader); // when a server receives a request, it joins or starts a new trace @@ -952,7 +987,7 @@ span = tracer.nextSpan(extractor.extract(request)); 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, as shown in the following example: // when you initialize the builder, define the extra field you want to propagate -tracingBuilder.propagationFactory( +Tracing.newBuilder().propagationFactory( ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "x-vcap-request-id") ); @@ -964,11 +999,16 @@ To ensure X-Ray can co-exist correctly, pass-through its tracing header, as show tracingBuilder.propagationFactory( ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "x-amzn-trace-id") ); -
+ +In Spring Cloud Sleuth all elements of the tracing builder Tracing.newBuilder() +are defined as beans. So if you want to pass a custom PropagationFactory, it’s enough +for you to create a bean of that type and we will set it in the Tracing bean. + +
Prefixed fields If they follow a common pattern, you can also prefix fields. The following example shows how to propagate x-vcap-request-id the field as-is but send the country-code and user-id fields on the wire as x-baggage-country-code and x-baggage-user-id, respectively: -tracingBuilder.propagationFactory( +Tracing.newBuilder().propagationFactory( ExtraFieldPropagation.newFactoryBuilder(B3Propagation.FACTORY) .addField("x-vcap-request-id") .addPrefixedFields("baggage-", Arrays.asList("country-code", "user-id")) @@ -1059,23 +1099,29 @@ Instead, look them up each time you need them. Current Span Brave supports a "current span" concept which represents the in-flight operation. You can use Tracer.currentSpan() to add custom tags to a span and Tracer.nextSpan() to create a child of whatever is in-flight. + In Sleuth, you can autowire the Tracer bean to retrieve the current span via tracer.currentSpan() method. To retrieve the current context just call tracer.currentSpan().context(). To get the current trace id as String you can use the traceIdString() method like this: tracer.currentSpan().context().traceIdString(). +
Setting a span in scope manually When writing new instrumentation, it is important to place a span you created in scope as the current span. Not only does doing so let users access it with Tracer.currentSpan(), but it also allows customizations such as SLF4J MDC to see the current trace IDs. Tracer.withSpanInScope(Span) facilitates this and is most conveniently employed by using the try-with-resources idiom. Whenever external code might be invoked (such as proceeding an interceptor or otherwise), place the span in scope, as shown in the following example: -try (SpanInScope ws = tracer.withSpanInScope(span)) { +@Autowired Tracer tracer; + +try (SpanInScope ws = tracer.withSpanInScope(span)) { return inboundRequest.invoke(); } finally { // note the scope is independent of the span span.finish(); } In edge cases, you may need to clear the current span temporarily (for example, launching a task that should not be associated with the current request). To do tso, pass null to withSpanInScope, as shown in the following example: -try (SpanInScope cleared = tracer.withSpanInScope(null)) { +@Autowired Tracer tracer; + +try (SpanInScope cleared = tracer.withSpanInScope(null)) { startBackgroundThread(); }
@@ -1540,8 +1586,7 @@ object, you will have to create a bean of zipkin2.reporter.Sender -See the Dalston Documentation -for how to create a Stream Zipkin server. +If for some reason you need to create the deprecated Stream Zipkin server, see the Dalston Documentation. Integrations @@ -1883,6 +1928,10 @@ into the message. so that tracing headers get injected into the created Spring Kafka’s Producer and Consumer. To block this feature, set spring.sleuth.messaging.kafka.enabled to false. + +We do not support context propagation via @KafkaListener annotation. +Check this issue for more information. +
@@ -1897,10 +1946,13 @@ To disable Zuul support, set the spring.sleuth.zuul.enabled p Check them out at the following links: -Zipkin for apps presented in the samples to the top +Zipkin for apps presented in the samples to the top. First make +a request to Service 1 and then check out the trace in Zipkin. -Zipkin for Brewery on PWS, its Github Code +Zipkin for Brewery on PWS, its Github Code. +Ensure that you’ve picked the lookback period of 7 days. If there are no traces, go to Presenting application +and order some beers. Then check Zipkin for traces.