Как Spring Cloud Sleuth распространяет контекст MD C в Webflux ouf из коробки, чтобы его содержимое могло быть зарегистрировано в разных потоках? - PullRequest
0 голосов
/ 24 апреля 2020

Я хотел бы знать, как Spring Cloud Sleuth распространяет контекст MD C между потоками, делая каждый из них доступным для параметров MD C.

Я читал эту статью https://simonbasle.github.io/2018/02/contextual-logging-with-reactor-context-and-mdc/, который предлагает использовать контекст подписчика для распространения состояния MD C между потоками.

Мне нужно сделать что-то похожее с другими параметрами из некоторых заголовков запросов, поэтому я создал, чтобы поместить его в MD C для текущего потока и сохраняет его в контексте подписчика. Однако следующий поток, который возобновляет выполнение, не имеет его в наличии. Каким-то образом я должен снова вызвать MD C в новом потоке, используя значение из контекста, но как?

@Slf4j
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ReactiveRequestCorrelationFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String principal = exchange.getRequest().getHeaders().getFirst("principal-header");
        MDC.put("principal", principal);
        return chain.filter(exchange)
                .subscriberContext(Context.of("principal", principal))
                .doOnTerminate(MDC::clear);
    }

}

Посмотрите на это отображение контроллера:

    @GetMapping(value = "/v1/departments", produces = MediaType.APPLICATION_JSON_VALUE)
    public Flux<Department> getDepartments() {
        log.info("getDepartaments");
        return webClient.get().uri("http://someService:8080/api/v1/departamentosFoo").retrieve().bodyToFlux(Departments.class)
                .doOnNext(dep -> log.info("found department {}", dep));
    }

Это создает этот журнал:

logging.pattern.console="%magenta([%thread]) [%X{traceId}] [%X{spanId}] [%X{principal}]  - %m%n"
[boundedElastic-2] [d0a916db8be0cbf7] [d0a916db8be0cbf7] []  - getDepartments
[boundedElastic-2] [d0a916db8be0cbf7] [fb2367685db70201] []  - found department Department(id=1, nombre=dep, fechaAlta=Fri Apr 24 14:16:20 CEST 2020, staff=1, tag=, empresa=true)
[reactor-http-nio-3] [d0a916db8be0cbf7] [d0a916db8be0cbf7] []  - found department Department(id=1, nombre=dep, fechaAlta=Fri Apr 24 14:16:20 CEST 2020, staff=1, tag=, empresa=true)

Запрос начался в потоке реактора-http-nio, а затем переключился на boundedElasti c -2. Как видите, отображаются значения traceId и spanId, но не те, которые я добавил в свой фильтр. Как Sleuth удалось распространить свой контекст (traceId spanId) в другие потоки?

Ответы [ 3 ]

1 голос
/ 25 апреля 2020

Проводя некоторые исследования, используя информацию, предоставленную Мартином в его ответе, я разработал ее следующим образом:

Обновлен фильтр:

@Slf4j
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE + 6)
public class ReactiveRequestCorrelationFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return chain.filter(exchange)
                .doOnSubscribe(s -> {
                    String principal = exchange.getRequest().getHeaders().getFirst("principal-header");
                    ExtraFieldPropagation.set("principal", principal);
                });
    }

}

application.yml

spring:
  sleuth:
    log:
      slf4j:
        whitelisted-mdc-keys: principal
    baggage-keys: principal

После этого мое настраиваемое поле стало отображаться в журналах, а Sleuth позаботился о его настройке и очистке от MD C:

[boundedElastic-2] [fadba73bf6447d02] [fadba73bf6447d02] [myprincipal] getDepartaments
1 голос
/ 07 мая 2020

Вам не нужно никаких настроек, чтобы заставить это работать. Все, что требуется для распространения пользовательских HTTP-заголовков, - это сообщить Sleuth о них:

#The one is on by default
spring.sleuth.log.slf4j.enabled=true

spring.sleuth.propagation-keys=principal-header
spring.sleuth.log.slf4j.whitelisted-mdc-keys=principal-header

(я использую версию свойств, но то же самое работает с yaml)

Затем в ваша конфигурация logback использует

[%X{principal-header}]

Вот и все!

NB Лично я предпочел бы удалить бит -header из имени заголовка.

0 голосов
/ 25 апреля 2020

Они используют Reactor Context вместе с Reactor Hooks. Соответствующий код из Spring-Cloud-Sleuth: ссылка

Пара других ссылок, которые могут быть полезны:

...