- Published on
Adding Micrometer Tracing to Spring Boot 3 Applications
- Authors
- Name
Guide for adding distributed logging to Spring boot 3 applications with Micrometer, Brave & Zipkin.
Required dependencies:
<!-- includes the micrometer dependency along with brave and zipkin -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Application configs:
→ Spring boot 3 will generate 128-bit trace ids following the w3c format.
→ Sampling probability can be between (0.0–1.0), representing how often Micrometer will generate trace logs.
management:
tracing:
enabled: true
sampling:
probability: 1.0
<!-- optional: for backwards compatability with spring2 b3 -->
spring:
sleuth:
propagation:
type: w3c,b3
Configuring Zipkin:
By default, data will be sent to Zipkin over the HTTP endpoint.
- To change the Zipkin server host, add the following configs:
management:
zipkin:
tracing:
endpoint: localhost:9411
- To disable Zipkin altogether, annotate the @SpringBootApplication class with the following:
@EnableAutoConfiguration(exclude {ZipkinAutoConfiguration.class})
- If instead, you want to push the trace logs to a Kafka topic and have Zipkin consume that topic, do the following:
- Add the Zipkin Kafka sender dependency:
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-kafka</artifactId>
</dependency>
- Add the following class to configure the Kafka topic:
@Configuration
@EnableConfigurationProperties(KafkaProperties.class)
public class ZipkinConfig {
@Bean("zipkinSender")
KafkaSender senderZipkin(KafkaProperties config, Environment environment) {
String topic = environment.getProperty("management.tracing.kafka.topic", "zipkin");
String serviceName = environment.getProperty("management.tracing.service.name", "server-name");
Map<String, Object> properties = config.buildProducerProperties();
properties.put("key.serializer", ByteArraySerializer.class.getName());
properties.put("value.serializer", ByteArraySerializer.class.getName());
properties.put(CommonClientConfigs.CLIENT_ID_CONFIG, serviceName);
properties.put("bootstrap.servers", "localhost:8888");
return KafkaSender.newBuilder().topic(topic).overrides(properties).build();
}
}
Creating the trace payload:
We have two options when it comes to the payload, either use a predefined pattern or implement the payload on the code level.
Micrometer pattern:
→ note that the trace and span id are not included by default.
logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]
Code level:
@Component
@RequiredArgsConstructor
public class LogTracer {
private final Tracer tracer;
public String getTraceId() {
String traceId = "";
try {
traceId = Objects.isNull(tracer.currentSpan()) ? tracer.nextSpan().context().traceIdString():
tracer.currentSpan().context().traceIdString();
} catch (Exception error) {
//error handling
}
return traceId;
}
public void logData(Object data){
createPayload(data, getTraceId()) //ex: implement the payload format then push to kibana logs
}
}
References:
- https://github.com/micrometer-metrics/tracing/wiki/Spring-Cloud-Sleuth-3.1-Migration-Guide#high-level-overview
- https://openvalue.blog/posts/2022/12/16/tracing-in-spring-boot-2-and-3/
- https://stackoverflow.com/questions/74853681/zipkin-sender-type-and-kafka-topic-not-working-after-updating-spring-boot-3
- https://github.com/spring-projects/spring-boot/issues/34620