[JAVA] Es scheint, dass MDC zwischen Anwendungen weitergegeben werden kann, indem der Kontext zusammen mit Spring WebFlux verwendet wird.

Vorwort

Um MDC mit Spring WebFlux zu verwenden, verwenden Sie den Kontext Ich schrieb über die Geschichte der Verbreitung von MDC zwischen Anwendungen. Ich werde. Die Kenntnis des obigen Artikels ist inhaltlich erforderlich.

Die Geschichte des Pioniers

Hauptthema

Heutzutage beliebte Mikrodienste haben verschiedene Komplikationen, von denen eine das Protokoll ist. Es besteht eine natürliche Anforderung, dass die Kommunikation, die von A-System-> B-System-> C-System fließt, später in einem einzigen Protokoll zusammengefasst wird, und es wurden verschiedene Methoden angewendet, um dies zu lösen. (Spring Sleuth usw.)

Auf die gleiche Weise bestand die Forderung, dass wir verschiedene Debug-Informationen gemeinsam übernehmen konnten, und unser System war nur davon betroffen.

Dieses Mal werde ich eine der Methoden aufgreifen, die in "Übergeben des Kontexts mit Spring Web Flux" eingeführt wurden.

Spezifischer Code

Um kurz zu schreiben, was WebFilter tut, was ich von nun an vorstellen werde

MdcHeaderFilter.java


import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import reactor.util.context.Context;

import java.util.Map;

import static java.util.stream.Collectors.toMap;
import static jp.co.example.helper.LogHelper.*;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MdcHeaderFilter implements WebFilter {
  private static final String MDC_HEADER_PREFIX = "X-MDC-";

  @Override
  public Mono<Void> filter(
    ServerWebExchange ex,
    WebFilterChain chain) {
    ex.getResponse().beforeCommit(
      () -> addContextToHttpResponseHeaders(ex.getResponse())
    );

    return chain.filter(ex)
      .subscriberContext(
        ctx -> addRequestHeadersToContext(ex.getRequest(), ctx)
      );
  }

  private Context addRequestHeadersToContext(
    final ServerHttpRequest request,
    final Context context) {

    final Map<String, String> contextMap = request
      .getHeaders().toSingleValueMap().entrySet()
      .stream()
      .filter(x -> x.getKey().startsWith(MDC_HEADER_PREFIX))
      .collect(
        toMap(v -> v.getKey().substring(MDC_HEADER_PREFIX.length()),
          Map.Entry::getValue
        )
      );

    //Wenn Sie beispielsweise ein Cookie setzen möchten, können Sie dies tun
    String cookie = request.getCookies().containsKey("EXAMPLE") ?
      request.getCookies().getFirst("EXAMPLE").getValue() : "none";
    contextMap.put("example-cookie", cookie);

    return context.put(CONTEXT_MAP, contextMap);
  }

  private Mono<Void> addContextToHttpResponseHeaders(
    final ServerHttpResponse res) {

    return Mono.subscriberContext().doOnNext(ctx -> {
      if (!ctx.hasKey(CONTEXT_MAP)) return;

      final HttpHeaders headers = res.getHeaders();
      ctx.<Map<String, String>>get(CONTEXT_MAP).forEach(
        (key, value) -> headers.add(MDC_HEADER_PREFIX + key, value)
      );
    }).then();
  }
}

Es ist sehr einfach zu machen, aber es ist vielseitig. Es kann auch verwendet werden, wenn Sie ein bestimmtes Cookie als Benutzerinformationen zum Debuggen verwenden müssen, wie z. B. unser ~~ F ● ck ~~ System.

Ende

Lassen Sie sich nicht von der Antwort einfangen, die Sie an Ihre Kunden erhalten!

Recommended Posts

Es scheint, dass MDC zwischen Anwendungen weitergegeben werden kann, indem der Kontext zusammen mit Spring WebFlux verwendet wird.
Sie verwenden den Kontext, um MDC mit Spring WebFlux zu verwenden
Objektorientiert, das von Feen verstanden werden kann