Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
73 views
in Technique[技术] by (71.8m points)

java - Allow ability to populate ServerWebExchange.LogPrefix in Spring WebFlux for UniqueRequestId logging

Spring Webflux offer Handlers which take a ServerRequest and is from where we implement our code. As per the following article Spring has a LogId concept which seems to be a what I refer to as a UniqueRequestId. When an exception is thrown the framework will put the LogId into the log entry via AbstractErrorWebExceptionHandler / ServerWebExchange. My situation relates to having many services calling each other and sharing a UniqueRequestId. So rather than Spring generating this ID we'd like a way to set the LogId via a HTTP Request Header e.g. X-Request-Id. My reason is so that the logs from one service can be related to the logs from another service. I can't find any articles on how to achieve this.

Some related background: I've managed a 90% partial alternate solution of getting a UniqueRequestId into the logs by setting the UniqueRequestId into MDC (ThreadLocal) and then passing it through the reactive chain based on this feature (https://projectreactor.io/docs/core/release/reference/#context -> see "Adding a Context to a Reactive Sequence"). This works for code handled within my reactive sequence + handler but if my code throws an Exception or Mono.error(...) then it seems the Spring WebFlux framework dispatches the logging to an async thread and therefore both the MDC and Context are lost. Hence I was hoping to bridge the final issue by poking my UniqueRequestId into the LogId.

https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-logging-id

Spring: Boot: 2.4.1, Web + WebFlux: 5.3.2

question from:https://stackoverflow.com/questions/65902383/allow-ability-to-populate-serverwebexchange-logprefix-in-spring-webflux-for-uniq

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Do you want specifically to implement yourself the correlation part using a UniqueRequestId?

If you only want the feature of being able to keep track of your processing on your services or across services then you should look at tracing solutions which can be commonly found in application performance monitoring libraries.

I think you could use spring-cloud-sleuth with only log correlation (https://cloud.spring.io/spring-cloud-sleuth/reference/html/#only-sleuth-log-correlation)

Sleuth supports reactor (spring webflux), it'll automatically add some data to your logs

  1. trace.id a trace represents an operation, or a data flow, that can happen on several services. To me this is what you are looking for, this trace is made to be sent to other services so that they reuse it in their logs. Allowing you to track a particular call over several services.
  2. transaction.id a transaction represents an operation, or a data flow inside the same service.

For example (the code below does not work, its just to give you an idea):

  • serviceA makes an HTTP call to serviceB, both running in different containers / JVM
public class serviceA() {

  private final ServiceBClient serviceBClient;

 ?@Get
  public Flux<Cat> getSomething() {
    log.info('Calling serviceB');
    return serviceBClient
      .listAllCats()
      .then(() -> {    log.info('Called serviceB') });
  }

}
public class serviceB() {

  private final CatRepository catRepository;

 ?@Get
  public Flux<Cat> listCats() {
    log.info('Asking for cats');
    return catRepository.listAll()
     .doOnSuccess(() -> { log.info('Request success!') })
  }

}

Below are example with custom log message (only care for the trace.id)
serviceA.log

[INFO] .... Calling serviceB, trace.id=1321313543121, transaction.id=123546   
[INFO] .... Called serviceB, trace.id=1321313543121, transaction.id=123546

serviceB.log

[INFO] .... Asking for cats, trace.id=1321313543121, transaction.id=224465   
[INFO] .... Called serviceB, trace.id=1321313543121, transaction.id=224465
  1. transaction.id, a transaction represent an operation on a specific service.

Sleuth should also the trace.id to error logs


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...