Spring Cloud Sleuth is a powerful tool for implementing log tracking in your application. You can use the Sleuth library to apply to scheduled tasks, multithreaded services, or complex Web requests, especially in a system that consists of multiple services. When we diagnose problems in these applications, even with logging it is difficult to tell what actions a request needs to correlate.
If you want to diagnose complex operations, the usual solution is to pass a unique ID in the request to each method to identify the log. Sleuth can be easily integrated with the log framework Logback, SLF4J, and uses log tracking and diagnostic issues by adding unique identifiers. 1. Dependency Management
Adding sleuth to the Spring Boot Web app is simple, just add the following dependencies in Pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId> Spring-cloud-starter-sleuth</artifactid>
</dependency>
Also add an app name to identify the application's log, add a line to the profile application.properties file
Spring.application.name=sleuth Tutorial
2. A simple Web application
First create a service
@Service public
class Sleuthservice {public
void Dosomeworksamespan () throws Interruptedexception {
Thread.Sleep (1000L);
Logger.info ("Doing some Work");
}
}
Then write a controller to invoke the service
@RestController public
class Sleuthcontroller {
@Autowired
private final sleuthservice sleuthservice;
@GetMapping ("/same-span") public
String Hellosleuthsamespan () throws Interruptedexception {
Logger.info (" Same Span ");
Sleuthservice.dosomeworksamespan ();
Return "Success";
}
}
Launch apps, Access Http://localhost:8080/same-span, view logs
2018-04-16 16:35:54.151 INFO [sleuth Tutorial,0afe3e67168fce4f,0afe3e67168fce4f,false] 5968---[nio-8080-exec-1 ] C.p.s.cloud.sleuth.sleuthcontroller : Same Span
2018-04-16 16:35:55.161 INFO [Sleuth Tutorial, 0AFE3E67168FCE4F,0AFE3E67168FCE4F,FALSE] 5968---[nio-8080-exec-1] c.p.spring.cloud.sleuth.sleuthservice : Doing some work
The format of the log is: [application name, traceid, spanid, export] application name - The name of the app, which is the property of the Spring.application.name parameter configuration in application.properties. Traceid -The ID number assigned to a request to identify a request link. Spanid -Represents a basic unit of work, a request can contain multiple steps, and each step has its own spanid. A request consists of a traceid, multiple Spanid export -Boolean types. Indicates whether to export this information to an aggregator like Zipkin for collection and presentation.
As you can see, Traceid and Spanid are the same in two logs, even if the message originates from two different classes. This can be done in different logs by looking for Traceid to identify a request. 3. Asynchronous thread pool
Add @async annotations implement asynchronous thread invocation, add a configuration class to build the thread pool
@Configuration
@EnableAsync Public
class Threadconfig extends asyncconfigurersupport{
@Autowired
Private Beanfactory beanfactory;
@Override public
Executor getasyncexecutor () {
Threadpooltaskexecutor threadpooltaskexecutor = new Threadpooltaskexecutor ();
Threadpooltaskexecutor.setcorepoolsize (7);
Threadpooltaskexecutor.setmaxpoolsize (a);
Threadpooltaskexecutor.setqueuecapacity (one);
Threadpooltaskexecutor.setthreadnameprefix ("myexecutor-");
Threadpooltaskexecutor.initialize ();
return new Lazytraceexecutor (Beanfactory, threadpooltaskexecutor);
}
}
Here we inherit asyncconfigurersupport specific asynchronous actuators, using Lazytraceexecutor to ensure that Traceid and Spanid are passed correctly, while adding @enableasync annotations to classes.
Then add an async method to the service:
@Async public
void Asyncmethod () throws Interruptedexception {
logger.info ("Start Async Method");
Thread.Sleep (1000L);
Logger.info ("End Async Method");
}
This service is also invoked in the controller.
@GetMapping ("/async") public
String Hellosleuthasync () throws Interruptedexception {
Logger.info ("before Async Method call ");
Sleuthservice.asyncmethod ();
Logger.info ("After Async Method call");
Return "Success";
}
To access Http://localhost:8080/async, view the log as follows:
2018-04-16 16:55:06.859 INFO [sleuth Tutorial,4bc16602ac8262d5,4bc16602ac8262d5,false] 5968---[nio-8080-exec-6 ] C.p.s.cloud.sleuth.sleuthcontroller : Before Async Method call
2018-04-16 16:55:06.872 INFO [Sleuth TUTORIAL,4BC16602AC8262D5,4BC16602AC8262D5,FALSE] 5968---[nio-8080-exec-6] C.p.s.cloud.sleuth.sleuthcontroller : After Async Method call
2018-04-16 16:55:06.905 INFO [Sleuth Tutorial,4bc16602ac8262d5, 4D216310C71E9C22,FALSE] 5968---[ MyExecutor-1] c.p.spring.cloud.sleuth.sleuthservice : Start Async Method
2018-04-16 16:55:07.905 INFO [sleuth Tutorial,4bc16602ac8262d5,4d216310c71e9c22,false] 5968---[ MyExecutor-1] C.p.spring.cloud.sleuth.sleuthservice : End Async Method
As an example, you can see that sleuth passed the Traceid into the async method and created the new Spanid, which represents the same request but enters another processing stage, executed by an asynchronous thread. 4. Scheduled Tasks
Now let's see how sleuth works in the @scheduled method, modifying the Threadconfig class is that it supports time scheduling.
@Configuration
@EnableAsync
@EnableScheduling public
class Threadconfig extends Asyncconfigurersupport
implements Schedulingconfigurer {
//...
@Override public
void Configuretasks (Scheduledtaskregistrar scheduledtaskregistrar) {
Scheduledtaskregistrar.setscheduler (Schedulingexecutor ());
}
@Bean (Destroymethod = "shutdown") public
Executor Schedulingexecutor () {
return Executors.newscheduledthreadpool (1);
}
}
Here we implement the Schedulingconfigurer interface and re-write the Configuretasks method, adding @enablescheduling annotations to the class.
Write a new scheduling service that defines a scheduled task that executes once every 3 seconds.
@Service public
class Schedulingservice {
private Logger Logger = Loggerfactory.getlogger (This.getclass ());
Private final Sleuthservice Sleuthservice;
@Autowired public
Schedulingservice (Sleuthservice sleuthservice) {
this.sleuthservice = Sleuthservice;
}
@Scheduled (Fixeddelay = 30000) public
void Scheduledwork () throws Interruptedexception {
logger.info ("Start Some work from the scheduled task ");
Sleuthservice.asyncmethod ();
Logger.info ("End Work from Scheduled Task");
}
}
Restart the app to wait for the task to execute and observe the log:
2018-04-16 17:10:20.232 INFO [sleuth Tutorial,5d891f56b6f18505,5d891f56b6f18505,false] 7936---[pool-1-thread-1] C.p.s.cloud.sleuth.schedulingservice:start some work from the scheduled task 2018-04-16 17:10:20.232 INFO [Sleuth T UTORIAL,5D891F56B6F18505,5D891F56B6F18505,FALSE] 7936---[pool-1-thread-1] c.p.s.cloud.sleuth.schedulingservice: End work from scheduled task 2018-04-16 17:10:20.232 INFO [sleuth Tutorial,5d891f56b6f18505,abe8b45c36f93be8,false] 7936 ---[MyExecutor-2] c.p.spring.cloud.sleuth.sleuthservice:start Async Method 2018-04-16 17:10:21.232 INFO [Sleuth TUTORIAL,5D891F56B6F18505,ABE8B45C36F93BE8,FALSE] 7936---[MyExecutor-2] c.p.spring.cloud.sleuth.sleuthservice:e nd Async Method 2018-04-16 17:10:50.235 INFO [sleuth Tutorial,0dd33d0764f0e6db,0dd33d0764f0e6db,false] 7936---[pool-1- THREAD-1] C.p.s.cloud.sleuth.schedulingservice:start Some work from the scheduled task 2018-04-16 17:10:50.235 INFO [Sleuth tutorial,0dd33d0764f0e6db,0DD33D0764F0E6DB,FALSE] 7936---[pool-1-thread-1] c.p.s.cloud.sleuth.schedulingservice:end work from scheduled task 2018-04-16 17:10:50.236 INFO [sleuth Tutorial,0dd33d0764f0e6db,5062d156f65a293e,false] 7936---[MyExecutor-3] C.p.spr Ing.cloud.sleuth.SleuthService:Start Async Method 2018-04-16 17:10:51.236 INFO [Sleuth tutorial,0dd33d0764f0e6db,506 2D156F65A293E,FALSE] 7936---[MyExecutor-3] c.p.spring.cloud.sleuth.sleuthservice:end Async Method
Here you can see that sleuth creates a new Traceid and Spanid for each task instance. 5. Summary
With this article we see Spring Cloud sleuth can be used in a wide variety of single Web applications. We can use this technique to easily collect logs for a request, even if the request spans multiple threads. It helps us to make clear debugging in multithreaded environments, identifying each step in each operation and operation by recognizing Traceid and Spanid, which can alleviate the complexity of our log analysis.
In addition to a single application, Spring Cloud Sleuth provides a complete set of solutions for distributed service tracking issues in the microservices architecture. The request can be applied to a request that is initiated through resttemplate, through a request passed by the Zuul proxy, through requests such as RABBITMQ, Kafka (or any other message middleware implemented by the spring Cloud stream binder).