Search code examples
javaspring-bootspring-cloud-sleuth

The way to stop sleuth fron creating new trace id for new threads


1.

Thread 1 Main thread

myClient.methohThaCallAnotherRemoteService();

2.

In my MyClient class we call another service by with restTeamplate

Single<MyObject> methohThaCallAnotherRemoteService() {

        return Single.fromCallable( () -> { ...

            final ResponseEntity<MyObject> response = restTemplate.postForEntity...

            return response.getBody();

        })
        .subscribeOn(Schedulers.io()); // to be run on separate threads / scheduler

3.

Then in ClientHttpRequestInterceptorImpl that is defined as

   ClientHttpRequestInterceptorImpl implements  org.springframework.http.client.ClientHttpRequestInterceptor {
     ...
 public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) { ...

     log.info("HTTP_CLIENT_REQUEST" + logResponse));

The problem is: That Sleuth creates a separate trace id (trace-id-2) with a span. The the log looks like this:

from main thread:

> INFO [my-app,trace-id-1, span-id-1] [nio-8080-exec-2] ...

from io thread:

> INFO [my-app,trace-id-2, span-id-2,false] 117037 ---
> [readScheduler-2] d.p.i.w.ClientHttpRequestInterceptorImpl :
> {"logType":"HTTP_CLIENT_REQUEST"

I would like trace-id-2 to be trace-id-1 so I could trance the request from the main thread to io thread. (otherwise it does not make sense in terms of tracing).

I still want my logger.info() to be inside the ClientHttpRequestInterceptorImpl

Q: How exactly it could be achieved?


Solution

  • To solve this problem I had to use LazyTraceExecutor - org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor

    Example of instance -ing it

    LazyTraceExecutor lazyTraceExecutor;
    
    @PostConstrucrt
    void init() {
          LazyTraceExecutor lazyTraceExecutor =  new LazyTraceExecutor(this.beanFactory,
                                                            java.util.concurrent.Executors.newFixedThreadPool(10, threadFactory("Sched-A-%d"))
                                                                    );
    }
    

    Then in my RX method that spawns new threads.

    Single<MyObject> methohThaCallAnotherRemoteService() {
    
            return Single.fromCallable( () -> { ...
    
                final ResponseEntity<MyObject> response = restTemplate.postForEntity...
    
                return response.getBody();
    
            })
            .subscribeOn(Schedulers.from(lazyTraceExecutor));  //  use it
    

    Now I have no problem with spans.