Spring Cloud Sleuth & Zipkin

Overview

Spring cloud sleuth helps you trace a request and zipkin server help you trace in a distributed environment.

Github: https://github.com/gitorko/project72

Spring Cloud Sleuth & Zipkin

How do you trace & debug a request in a single server? Now when it is deployed in pods and scaled how do you trace a request in a distributed environment? Spring Cloud Sleuth help you trace a request by appending unique trace id in the log statements. You can the publish such traces to the zipkin server which lets you visualize a request across distributed environment. You can then see the latency of each request in a distributed transaction.

Internally it has 4 modules –

  1. Collector – Once any component sends the trace data arrives to Zipkin collector daemon, it is validated, stored, and indexed for lookups by the Zipkin collector.
  2. Storage – This module store and index the lookup data in backend. Cassandra, ElasticSearch and MySQL are supported.
  3. Search – This module provides a simple JSON API for finding and retrieving traces stored in backend. The primary consumer of this API is the Web UI.
  4. Web UI – A very nice UI interface for viewing traces.

Code

 1package com.demo.project72.service;
 2
 3import java.util.concurrent.TimeUnit;
 4
 5import brave.Span;
 6import brave.Tracer;
 7import lombok.RequiredArgsConstructor;
 8import lombok.SneakyThrows;
 9import lombok.extern.slf4j.Slf4j;
10import org.springframework.scheduling.annotation.Async;
11import org.springframework.scheduling.annotation.EnableAsync;
12import org.springframework.stereotype.Service;
13
14@Service
15@Slf4j
16@EnableAsync
17@RequiredArgsConstructor
18public class GreetService {
19
20    private final Tracer tracer;
21
22    @SneakyThrows
23    public void doSomeWorkSameSpan() {
24        TimeUnit.SECONDS.sleep(1);
25        log.info("Work Span");
26    }
27
28    public void doSomeWorkNewSpan() throws InterruptedException {
29        log.info("Original span");
30        Span newSpan = tracer.nextSpan().name("newSpan").start();
31        try (Tracer.SpanInScope ws = tracer.withSpanInScope(newSpan.start())) {
32            TimeUnit.SECONDS.sleep(1);
33            log.info("New Span");
34        } finally {
35            newSpan.finish();
36        }
37        log.info("Original span");
38    }
39
40    @Async
41    public void asyncMethod() throws InterruptedException {
42        log.info("Start Async Method");
43        TimeUnit.SECONDS.sleep(1);
44        log.info("End Async Method");
45    }
46}
 1package com.demo.project72.config;
 2
 3import java.util.concurrent.Executor;
 4
 5import lombok.RequiredArgsConstructor;
 6import org.springframework.beans.factory.BeanFactory;
 7import org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor;
 8import org.springframework.context.annotation.Configuration;
 9import org.springframework.scheduling.annotation.AsyncConfigurer;
10import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
11
12@Configuration
13@RequiredArgsConstructor
14class ThreadConfig implements AsyncConfigurer {
15
16    private final BeanFactory beanFactory;
17
18    @Override
19    public Executor getAsyncExecutor() {
20        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
21        threadPoolTaskExecutor.setCorePoolSize(1);
22        threadPoolTaskExecutor.setMaxPoolSize(1);
23        threadPoolTaskExecutor.initialize();
24        return new LazyTraceExecutor(beanFactory, threadPoolTaskExecutor);
25    }
26
27}
 1spring:
 2  main:
 3    banner-mode: "off"
 4  application:
 5    name: project72
 6  sleuth:
 7    enabled: true
 8    sampler:
 9      probability: 1.0
10  zipkin:
11    base-url: http://localhost:9411/
12    enabled: true
13    sender:
14      type: web
15    service:
16      name: my-service

Setup

Project 72

Spring Cloud Sleuth & Zipkin

https://gitorko.github.io/spring-cloud-sleuth-zipkin/

Version

Check version

1$java --version
2openjdk 17.0.3 2022-04-19 LTS

Zipkin

To run zipkin server use the docker command

1docker run -d -p 9411:9411 --name my-zipkin openzipkin/zipkin
2docker stop my-zipkin
3docker start my-zipkin

Login to zipkin UI, wait for few seconds for server to be up.

http://localhost:9411/zipkin/

Dev

To run the code.

1./gradlew clean build
2./gradlew bootRun

Testing

Invoke the rest api and notice the trace

http://localhost:8080/hello-span

http://localhost:8080/hello-new-span

http://localhost:8080/hello-async

You can now view the trace in zipkin UI

References

https://cloud.spring.io/spring-cloud-sleuth/

https://zipkin.io/

comments powered by Disqus