Tracing

Spring Boot Actuator provides dependency management and auto-configuration for Micrometer Tracing, a facade for popular tracer libraries.

To learn more about Micrometer Tracing capabilities, see its reference documentation.

Supported Tracers

Spring Boot ships auto-configuration for the following tracers:

Getting Started

We need an example application that we can use to get started with tracing. For our purposes, the simple “Hello World!” web application that’s covered in the “Developing Your First Spring Boot Application” section will suffice. We’re going to use the OpenTelemetry tracer with Zipkin as trace backend.

To recap, our main application code looks like this:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class MyApplication {

	private static final Log logger = LogFactory.getLog(MyApplication.class);

	@RequestMapping("/")
	String home() {
		logger.info("home() has been called");
		return "Hello World!";
	}

	public static void main(String[] args) {
		SpringApplication.run(MyApplication.class, args);
	}

}
There’s an added logger statement in the home() method, which will be important later.

Now we have to add the following dependencies:

  • org.springframework.boot:spring-boot-starter-actuator

  • io.micrometer:micrometer-tracing-bridge-otel - which is needed to bridge the Micrometer Observation API to OpenTelemetry.

  • io.opentelemetry:opentelemetry-exporter-zipkin - which is needed to report traces to Zipkin.

Add the following application properties:

  • Properties

  • YAML

management.tracing.sampling.probability=1
management.tracing.sampling.probability: 1.0

By default, Spring Boot samples only 10% of requests to prevent overwhelming the trace backend. This property switches it to 100% so that every request is sent to the trace backend.

To collect and visualize the traces, we need a running trace backend. We use Zipkin as our trace backend here. The Zipkin Quickstart guide provides instructions how to start Zipkin locally.

After Zipkin is running, you can start your application.

If you open a web browser to localhost:8080, you should see the following output:

Hello World!

Behind the scenes, an observation has been created for the HTTP request, which in turn gets bridged to OpenTelemetry, which reports a new trace to Zipkin.

Now open the Zipkin UI at localhost:9411 and press the "Run Query" button to list all collected traces. You should see one trace. Press the "Show" button to see the details of that trace.

You can include the current trace and span id in the logs by setting the logging.pattern.level property to %5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]

Tracer Implementations

As Micrometer Tracer supports multiple tracer implementations, there are multiple dependency combinations possible with Spring Boot.

All tracer implementations need the org.springframework.boot:spring-boot-starter-actuator dependency.

OpenTelemetry With Zipkin

  • io.micrometer:micrometer-tracing-bridge-otel - which is needed to bridge the Micrometer Observation API to OpenTelemetry.

  • io.opentelemetry:opentelemetry-exporter-zipkin - which is needed to report traces to Zipkin.

OpenTelemetry With Wavefront

  • io.micrometer:micrometer-tracing-bridge-otel - which is needed to bridge the Micrometer Observation API to OpenTelemetry.

  • io.micrometer:micrometer-tracing-reporter-wavefront - which is needed to report traces to Wavefront.

OpenZipkin Brave With Zipkin

  • io.micrometer:micrometer-tracing-bridge-brave - which is needed to bridge the Micrometer Observation API to Brave.

  • io.zipkin.reporter2:zipkin-reporter-brave - which is needed to report traces to Zipkin.

If your project doesn’t use Spring MVC or Spring WebFlux, the io.zipkin.reporter2:zipkin-sender-urlconnection dependency is needed, too.

OpenZipkin Brave With Wavefront

  • io.micrometer:micrometer-tracing-bridge-brave - which is needed to bridge the Micrometer Observation API to Brave.

  • io.micrometer:micrometer-tracing-reporter-wavefront - which is needed to report traces to Wavefront.

Integration with Micrometer Observation

A TracingAwareMeterObservationHandler is automatically registered on the ObservationRegistry, which creates spans for every completed observation.

Creating Custom Spans

You can create your own spans by starting an observation. For this, inject ObservationRegistry into your component:

import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;

import org.springframework.stereotype.Component;

@Component
class CustomObservation {

	private final ObservationRegistry observationRegistry;

	CustomObservation(ObservationRegistry observationRegistry) {
		this.observationRegistry = observationRegistry;
	}

	void someOperation() {
		Observation observation = Observation.createNotStarted("some-operation", this.observationRegistry);
		observation.lowCardinalityKeyValue("some-tag", "some-value");
		observation.observe(() -> {
			// Business logic ...
		});
	}

}

This will create an observation named "some-operation" with the tag "some-tag=some-value".

If you want to create a span without creating a metric, you need to use the lower-level Tracer API from Micrometer.