我引用了博客文章Contextual Logging with Reactor Context and MDC,但我不知道如何在WebFilter中访问反应堆上下文。
@Component
public class RequestIdFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
List<String> myHeader = exchange.getRequest().getHeaders().get("X-My-Header");
if (myHeader != null && !myHeader.isEmpty()) {
MDC.put("myHeader", myHeader.get(0));
}
return chain.filter(exchange);
}
}
答案 0 :(得分:6)
您可以执行类似于以下的操作,可以为您喜欢的任何类设置TypeError: Cannot read property 'root' of undefined
at new dt (/Users/eduardo/sites/tr2/dist/server.js:2176:2142)
at /Users/eduardo/sites/tr2/dist/server.js:409:1427
at Wi (/Users/eduardo/sites/tr2/dist/server.js:409:1644)
at /Users/eduardo/sites/tr2/dist/server.js:424:8973
at new e (/Users/eduardo/sites/tr2/dist/server.js:424:8983)
at Object.go [as createNgModuleRef] (/Users/eduardo/sites/tr2/dist/server.js:424:8621)
at n.create (/Users/eduardo/sites/tr2/dist/server.js:482:635)
at /Users/eduardo/sites/tr2/dist/server.js:229:1479
at e.invoke (/Users/eduardo/sites/tr2/dist/server.js:2907:7001)
at Object.onInvoke (/Users/eduardo/sites/tr2/dist/server.js:215:2040)
,在本示例中,我仅使用标头-但是自定义类就可以了。
如果在此处进行设置,则任何带有处理程序等的日志记录也将有权访问Angular CLI: 6.1.2
Node: 9.11.1
OS: darwin x64
Angular: 6.1.1
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, platform-server, router
Package Version
@angular-devkit/architect 0.7.2
@angular-devkit/build-angular 0.7.2
@angular-devkit/build-optimizer 0.7.2
@angular-devkit/build-webpack 0.7.2
@angular-devkit/core 0.7.2
@angular-devkit/schematics 0.7.2
@angular/cdk 6.2.1
@angular/cli 6.1.2
@angular/material 6.2.1
@ngtools/webpack 6.1.2
@schematics/angular 0.7.2
@schematics/update 0.7.2
rxjs 6.2.2
typescript 2.9.2
webpack 4.9.2
。
下面的context
设置MDC并在之后清除它。显然,可以用任何您喜欢的东西代替它。
context
答案 1 :(得分:3)
这是一种基于最新方法的解决方案,截至 2021 年 5 月,取自 official documentation:
Measure-Command
假设您的 import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
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.core.publisher.Signal;
import reactor.util.context.Context;
@Slf4j
@Configuration
public class RequestIdFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String requestId = getRequestId(request.getHeaders());
return chain
.filter(exchange)
.doOnEach(logOnEach(r -> log.info("{} {}", request.getMethod(), request.getURI())))
.contextWrite(Context.of("CONTEXT_KEY", requestId));
}
private String getRequestId(HttpHeaders headers) {
List<String> requestIdHeaders = headers.get("X-Request-ID");
return requestIdHeaders == null || requestIdHeaders.isEmpty()
? UUID.randomUUID().toString()
: requestIdHeaders.get(0);
}
public static <T> Consumer<Signal<T>> logOnEach(Consumer<T> logStatement) {
return signal -> {
String contextValue = signal.getContextView().get("CONTEXT_KEY");
try (MDC.MDCCloseable cMdc = MDC.putCloseable("MDC_KEY", contextValue)) {
logStatement.accept(signal.get());
}
};
}
public static <T> Consumer<Signal<T>> logOnNext(Consumer<T> logStatement) {
return signal -> {
if (!signal.isOnNext()) return;
String contextValue = signal.getContextView().get("CONTEXT_KEY");
try (MDC.MDCCloseable cMdc = MDC.putCloseable("MDC_KEY", contextValue)) {
logStatement.accept(signal.get());
}
};
}
}
中有以下行:
application.properties
那么每次调用端点时,您的服务器日志都会包含这样的日志:
logging.pattern.level=[%X{MDC_KEY}] %5p
每次您想在响应式上下文中手动记录某些内容时,您都需要将以下内容添加到响应式链中:
2021-05-06 17:07:41.852 [60b38305-7005-4a05-bac7-ab2636e74d94] INFO 20158 --- [or-http-epoll-6] my.package.RequestIdFilter : GET http://localhost:12345/my-endpoint/444444/
如果您希望将 .doOnEach(logOnNext(r -> log.info("Something")))
传播到其他服务以进行分布式跟踪,您需要从响应式上下文(而不是从 MDC)读取它并使用以下内容包装您的 X-Request-ID
代码:< /p>
WebClient