Способ остановить сыщика при создании нового идентификатора трассировки для новых потоков - PullRequest
0 голосов
/ 07 мая 2020

1.

Поток 1 Основной поток

myClient.methohThaCallAnotherRemoteService();

2.

В моем классе MyClient мы вызываем другую службу с помощью 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.

Затем в ClientHttpRequestInterceptorImpl это определяется как

   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));

Проблема: Этот сыщик создает отдельный идентификатор трассировки ( trace-id-2) с промежутком. Журнал выглядит так:

из основного потока:

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

из потока io:

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

Я бы хотел trace-id-2 быть trace-id-1, чтобы я мог транслировать запрос из основного потока в поток io. (иначе это не имеет смысла с точки зрения трассировки).

Я все еще хочу, чтобы мой logger.info() находился внутри ClientHttpRequestInterceptorImpl

Q: Как именно этого можно было достичь?

Ответы [ 3 ]

0 голосов
/ 20 мая 2020

Я не очень разбираюсь в этом, но я видел некоторую помощь от https://gitter.im/spring-cloud/spring-cloud-sleuth?at=5eb2b6f397338850a2ee2b3f

некоторые советы, вставленные здесь:

https://github.com/spring-cloud/spring-cloud-sleuth/issues/1570#issuecomment -627181235

вы можете сначала попробовать выполнить подписку, а затем «потом» вашу вызываемую оболочку

0 голосов
/ 24 мая 2020

Для решения этой проблемы мне нужно использовать LazyTraceExecutor - org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor

Пример создания экземпляра

LazyTraceExecutor lazyTraceExecutor;

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

Затем в моем методе RX, который порождает новые потоки.

Single<MyObject> methohThaCallAnotherRemoteService() {

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

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

            return response.getBody();

        })
        .subscribeOn(Schedulers.from(lazyTraceExecutor));  //  use it

Теперь у меня нет проблем с пролетами.

0 голосов
/ 08 мая 2020

Я думаю, вы могли бы продолжить основной диапазон, например

https://cloud.spring.io/spring-cloud-sleuth/reference/html/#continuing -spans-2

// method declaration
@ContinueSpan(log = "testMethod11")
void testMethod11(@SpanTag("testTag11") String param);

// method execution
this.testBean.testMethod11("test");
this.testBean.testMethod13();

или

https://cloud.spring.io/spring-cloud-sleuth/reference/html/#continuing -spans

// let's assume that we're in a thread Y and we've received
// the `initialSpan` from thread X
Span continuedSpan = this.tracer.toSpan(newSpan.context());
try {
    // ...
    // You can tag a span
    continuedSpan.tag("taxValue", taxValue);
    // ...
    // You can log an event on a span
    continuedSpan.annotate("taxCalculated");
}
finally {
    // Once done remember to flush the span. That means that
    // it will get reported but the span itself is not yet finished
    continuedSpan.flush();
}

или

https://cloud.spring.io/spring-cloud-sleuth/reference/html/#creating -spans-with-explicit-parent

// let's assume that we're in a thread Y and we've received
// the `initialSpan` from thread X. `initialSpan` will be the parent
// of the `newSpan`
Span newSpan = null;
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(initialSpan)) {
    newSpan = this.tracer.nextSpan().name("calculateCommission");
    // ...
    // You can tag a span
    newSpan.tag("commissionValue", commissionValue);
    // ...
    // You can log an event on a span
    newSpan.annotate("commissionCalculated");
}
finally {
    // Once done remember to finish the span. This will allow collecting
    // the span to send it to Zipkin. The tags and events set on the
    // newSpan will not be present on the parent
    if (newSpan != null) {
        newSpan.finish();
    }
}

или

https://cloud.spring.io/spring-cloud-sleuth/reference/html/#runnable -and-callable

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        // do some work
    }

    @Override
    public String toString() {
        return "spanNameFromToStringMethod";
    }
};
// Manual `TraceRunnable` creation with explicit "calculateTax" Span name
Runnable traceRunnable = new TraceRunnable(this.tracing, spanNamer, runnable,
        "calculateTax");
// Wrapping `Runnable` with `Tracing`. That way the current span will be available
// in the thread of `Runnable`
Runnable traceRunnableFromTracer = this.tracing.currentTraceContext()
        .wrap(runnable);

В следующем примере показано, как это сделать для Callable:

Callable<String> callable = new Callable<String>() {
    @Override
    public String call() throws Exception {
        return someLogic();
    }

    @Override
    public String toString() {
        return "spanNameFromToStringMethod";
    }
};
// Manual `TraceCallable` creation with explicit "calculateTax" Span name
Callable<String> traceCallable = new TraceCallable<>(this.tracing, spanNamer,
        callable, "calculateTax");
// Wrapping `Callable` with `Tracing`. That way the current span will be available
// in the thread of `Callable`
Callable<String> traceCallableFromTracer = this.tracing.currentTraceContext()
        .wrap(callable);

Таким образом, вы гарантируете, что новый диапазон будет создан и закрыт для каждого выполнения.

...