# Using Spring Cloud Sleuth

This section goes into more detail about how you should use Spring Cloud Sleuth. It covers topics such as controlling the span lifecycle with Spring Cloud Sleuth API or via annotations. We also cover some Spring Cloud Sleuth best practices.

If you are starting out with Spring Cloud Sleuth, you should probably read the Getting Started guide before diving into this section.

## 1. Span Lifecycle with Spring Cloud Sleuth’s API

Spring Cloud Sleuth Core in its `api` module contains all necessary interfaces to be implemented by a tracer. The project comes with OpenZipkin Brave implementation. You can check how the tracers are bridged to the Sleuth’s API by looking at the `org.springframework.cloud.sleuth.brave.bridge`.

The most commonly used interfaces are:

- `org.springframework.cloud.sleuth.Tracer` - Using a tracer, you can create a root span capturing the critical path of a request.

- `org.springframework.cloud.sleuth.Span` - Span is a single unit of work that needs to be started and stopped. Contains timing information and events and tags.

You can also use your tracer implementation’s API directly.

Let’s look at the following Span lifecycle actions.

- start: When you start a span, its name is assigned and the start timestamp is recorded.

- end: The span gets finished (the end time of the span is recorded) and, if the span is sampled, it is eligible for collection (e.g. to Zipkin).

- continue: The span gets continued e.g. in another thread.

- create with explicit parent: You can create a new span and set an explicit parent for it.

| Spring Cloud Sleuth creates an instance of `Tracer` for you. In order to use it, you can autowire it.

### 1.1. Creating and Ending Spans

You can manually create spans by using the `Tracer`, as shown in the following example:

    // Start a span. If there was a span present in this thread it will become
    // the `newSpan`'s parent.
    Span newSpan = this.tracer.nextSpan().name("calculateTax");
    try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
        // ...
        // You can tag a span
        newSpan.tag("taxValue", taxValue);
        // ...
        // You can log an event on a span
        newSpan.event("taxCalculated");
    }
    finally {
        // Once done remember to end the span. This will allow collecting
        // the span to send it to a distributed tracing system e.g. Zipkin
        newSpan.end();
    }

In the preceding example, we could see how to create a new instance of the span. If there is already a span in this thread, it becomes the parent of the new span.

| Always clean after you create a span.

| If your span contains a name greater than 50 chars, that name is truncated to 50 chars. Your names have to be explicit and concrete. Big names lead to latency issues and sometimes even exceptions.

### 1.2. Continuing Spans

Sometimes, you do not want to create a new span but you want to continue one. An example of such a situation might be as follows:

- AOP: If there was already a span created before an aspect was reached, you might not want to create a new span.

To continue a span, you can store the span in one thread and pass it on to another one as shown in the example below.

    Span spanFromThreadX = this.tracer.nextSpan().name("calculateTax");
    try (Tracer.SpanInScope ws = this.tracer.withSpan(spanFromThreadX.start())) {
        executorService.submit(() -> {
            // Pass the span from thread X
            Span continuedSpan = spanFromThreadX;
            // ...
            // You can tag a span
            continuedSpan.tag("taxValue", taxValue);
            // ...
            // You can log an event on a span
            continuedSpan.event("taxCalculated");
        }).get();
    }
    finally {
        spanFromThreadX.end();
    }

### 1.3. Creating a Span with an explicit Parent

You might want to start a new span and provide an explicit parent of that span. Assume that the parent of a span is in one thread and you want to start a new span in another thread. Whenever you call `Tracer.nextSpan()`, it creates a span in reference to the span that is currently in scope. You can put the span in scope and then call `Tracer.nextSpan()`, as shown in the following example:

    // let's assume that we're in a thread Y and we've received
    // the `initialSpan` from thread X. `initialSpan` will be the parent
    // of the `newSpan`
    Span newSpan = null;
    try (Tracer.SpanInScope ws = this.tracer.withSpan(initialSpan)) {
        newSpan = this.tracer.nextSpan().name("calculateCommission");
        // ...
        // You can tag a span
        newSpan.tag("commissionValue", commissionValue);
        // ...
        // You can log an event on a span
        newSpan.event("commissionCalculated");
    }
    finally {
        // Once done remember to end the span. This will allow collecting
        // the span to send it to e.g. Zipkin. The tags and events set on the
        // newSpan will not be present on the parent
        if (newSpan != null) {
            newSpan.end();
        }
    }

| After creating such a span, you must finish it. Otherwise it is not reported (e.g. to Zipkin).

You can also use the `Tracer.nextSpan(Span parentSpan)` version to provide the parent span explicitly.

## 2. Naming Spans

Picking a span name is not a trivial task. A span name should depict an operation name. The name should be low cardinality, so it should not include identifiers.

Since there is a lot of instrumentation going on, some span names are artificial:

- `controller-method-name` when received by a Controller with a method name of `controllerMethodName`

- `async` for asynchronous operations done with wrapped `Callable` and `Runnable` interfaces.

- Methods annotated with `@Scheduled` return the simple name of the class.

Fortunately, for asynchronous processing, you can provide explicit naming.

### 2.1. `@SpanName` Annotation

You can name the span explicitly by using the `@SpanName` annotation, as shown in the following example:

    @SpanName("calculateTax")
    class TaxCountingRunnable implements Runnable {

        @Override
        public void run() {
            // perform logic
        }

    }

In this case, when processed in the following manner, the span is named `calculateTax`:

    Runnable runnable = new TraceRunnable(this.tracer, spanNamer, new TaxCountingRunnable());
    Future<?> future = executorService.submit(runnable);
    // ... some additional logic ...
    future.get();

### 2.2. `toString()` Method

It is pretty rare to create separate classes for `Runnable` or `Callable`. Typically, one creates an anonymous instance of those classes. You cannot annotate such classes. To overcome that limitation, if there is no `@SpanName` annotation present, we check whether the class has a custom implementation of the `toString()` method.

Running such code leads to creating a span named `calculateTax`, as shown in the following example:

    Runnable runnable = new TraceRunnable(this.tracer, spanNamer, new Runnable() {
        @Override
        public void run() {
            // perform logic
        }

        @Override
        public String toString() {
            return "calculateTax";
        }
    });
    Future<?> future = executorService.submit(runnable);
    // ... some additional logic ...
    future.get();

## 3. Managing Spans with Annotations

There are a number of good reasons to manage spans with annotations, including:

- API-agnostic means to collaborate with a span. Use of annotations lets users add to a span with no library dependency on a span api. Doing so lets Sleuth change its core API to create less impact to user code.

- Reduced surface area for basic span operations. Without this feature, you must use the span api, which has lifecycle commands that could be used incorrectly. By only exposing scope, tag, and log functionality, you can collaborate without accidentally breaking span lifecycle.

- Collaboration with runtime generated code. With libraries such as Spring Data and Feign, the implementations of interfaces are generated at runtime. Consequently, span wrapping of objects was tedious. Now you can provide annotations over interfaces and the arguments of those interfaces.

### 3.1. Creating New Spans

If you do not want to create local spans manually, you can use the `@NewSpan` annotation. Also, we provide the `@SpanTag` annotation to add tags in an automated fashion.

Now we can consider some examples of usage.

    @NewSpan
    void testMethod();

Annotating the method without any parameter leads to creating a new span whose name equals the annotated method name.

    @NewSpan("customNameOnTestMethod4")
    void testMethod4();

If you provide the value in the annotation (either directly or by setting the `name` parameter), the created span has the provided value as the name.

    // method declaration
    @NewSpan(name = "customNameOnTestMethod5")
    void testMethod5(@SpanTag("testTag") String param);

    // and method execution
    this.testBean.testMethod5("test");

You can combine both the name and a tag. Let’s focus on the latter. In this case, the value of the annotated method’s parameter runtime value becomes the value of the tag. In our sample, the tag key is `testTag`, and the tag value is `test`.

    @NewSpan(name = "customNameOnTestMethod3")
    @Override
    public void testMethod3() {
    }

You can place the `@NewSpan` annotation on both the class and an interface. If you override the interface’s method and provide a different value for the `@NewSpan` annotation, the most concrete one wins (in this case `customNameOnTestMethod3` is set).

### 3.2. Continuing Spans

If you want to add tags and annotations to an existing span, you can use the `@ContinueSpan` annotation, as shown in the following example:

    // method declaration
    @ContinueSpan(log = "testMethod11")
    void testMethod11(@SpanTag("testTag11") String param);

    // method execution
    this.testBean.testMethod11("test");
    this.testBean.testMethod13();

(Note that, in contrast with the `@NewSpan` annotation ,you can also add logs with the `log` parameter.)

That way, the span gets continued and:

- Log entries named `testMethod11.before` and `testMethod11.after` are created.

- If an exception is thrown, a log entry named `testMethod11.afterFailure` is also created.

- A tag with a key of `testTag11` and a value of `test` is created.

### 3.3. Advanced Tag Setting

There are 3 different ways to add tags to a span. All of them are controlled by the `SpanTag` annotation. The precedence is as follows:

1. Try with a bean of `TagValueResolver` type and a provided name.

2. If the bean name has not been provided, try to evaluate an expression. We search for a `TagValueExpressionResolver` bean. The default implementation uses SPEL expression resolution. IMPORTANT You can only reference properties from the SPEL expression. Method execution is not allowed due to security constraints.

3. If we do not find any expression to evaluate, return the `toString()` value of the parameter.

#### 3.3.1. Custom Extractor

The value of the tag for the following method is computed by an implementation of `TagValueResolver` interface. Its class name has to be passed as the value of the `resolver` attribute.

Consider the following annotated method:

    @NewSpan
    public void getAnnotationForTagValueResolver(
            @SpanTag(key = "test", resolver = TagValueResolver.class) String test) {
    }

Now further consider the following `TagValueResolver` bean implementation:

    @Bean(name = "myCustomTagValueResolver")
    public TagValueResolver tagValueResolver() {
        return parameter -> "Value from myCustomTagValueResolver";
    }

The two preceding examples lead to setting a tag value equal to `Value from myCustomTagValueResolver`.

#### 3.3.2. Resolving Expressions for a Value

Consider the following annotated method:

    @NewSpan
    public void getAnnotationForTagValueExpression(
            @SpanTag(key = "test", expression = "'hello' + ' characters'") String test) {
    }

No custom implementation of a `TagValueExpressionResolver` leads to evaluation of the SPEL expression, and a tag with a value of `hello characters` is set on the span. If you want to use some other expression resolution mechanism, you can create your own implementation of the bean.

#### 3.3.3. Using The `toString()` Method

Consider the following annotated method:

    @NewSpan
    public void getAnnotationForArgumentToString(@SpanTag("test") Long param) {
    }

Running the preceding method with a value of `15` leads to setting a tag with a String value of `"15"`.

## 4. What to Read Next

You should now understand how you can use Spring Cloud Sleuth and some best practices that you should follow. You can now go on to learn about specific Spring Cloud Sleuth features, or you could skip ahead and read about the integrations available in Spring Cloud Sleuth.