SpringBoot MDC只用于下一个日志



关于SpringBoot应用程序的一个小问题,请提供MDC日志。

我有一个非常简单的SpringBoot web处理器:

@GetMapping(path = "/mdcOnlyToThisLogPlease")
public Mono<String> mdcOnlyToThisLogPlease(@RequestBody Book book) {
MDC.setContextMap(Map.of("bookName", book.getTitle(), "bookAuthor", book.getAuthor()));
LOGGER.info("I would like to have a log with bookName and bookValue as first level key for the MDC Json log, and only for this log please");
return bookService.doSomething(book.getTitle(), book.getAuthor());
}

在这里,我想在json中记录书名和作者的第一层键,我想得到这个:

{ 
@timestamp:  2022-02-22T02:22:22.222Z 
@version:  1 
bookName: someName
bookAuthor: someAuthor
level:  INFO 
level_value:  20000 
logger_name:  MyClass 
message: I would like to have a log with bookName and bookValue as first level key for the MDC Json log, and only for this log please
spanId:  e58ad767e34525de 
thread_name:  reactor-http-epoll-1 
traceId:  ccf32f0b5d210aa2 
}

我认为这段代码可以做到这一点。不幸的是,它还记录了密钥,对于后面的每个日志!

例如,我还在bookService.doSomething()的日志中看到健康检查日志,以及更多…


{
@timestamp:  2022-05-02T04:31:30.648Z 
@version:  1 
bookName: someName
bookAuthor: someAuthor
level:  INFO 
level_value:  20000 
logger_name:  reactor.netty.http.server.AccessLog 
message:  0:0:0:0:0:0:0:1%0 - - [02/May/2022:04:31:30 +0000] "GET /health/readiness HTTP/2.0" 200 5088 19 
thread_name:  reactor-http-epoll-1 
}
{
@timestamp:  2022-05-02T04:33:30.648Z 
@version:  1 
bookName: someName
bookAuthor: someAuthor
level:  INFO 
level_value:  20000 
logger_name:  bookService 
message:  Log from book service. I do not wish to see bookName and bookAuthor as keys
thread_name:  reactor-http-epoll-1 
}
{ 
@timestamp:  2022-05-02T04:40:48.742Z 
@version:  1 
bookName: someName
bookAuthor: someAuthor
level:  INFO 
level_value:  20000 
logger_name:  reactor.netty.http.server.AccessLog 
message:  0:0:0:0:0:0:0:1%0 - - [02/May/2022:04:40:48 +0000] "GET /health/liveness HTTP/2.0" 200 5088 25 
thread_name:  reactor-http-epoll-1 
}

请问如何添加密钥,但只针对下一个/一个日志?

谢谢

假设您正在使用SLF4J MDC-

对于单个键值对,MDC附带MDCCloseable,它允许您利用使用资源的尝试块:

log.info("This will be logged without myKey, myValue");
try (MDC.MDCCloseable ignored = MDC.putCloseable("myKey", "myValue")) {
log.info("This will be logged with myKey, myValue");
}
log.info("This will be logged without myKey, myValue");

在此表单中,您放入MDC.putCloseable(...)中的条目将在块结束时自动删除。参见Javadocs

不幸的是,没有类似的方便方法来执行多个。一次输入。可以嵌套多个try-with-resources/MDC.putCloseable()块,但这样做会使代码混乱。

幸运的是,编写自己的代码并不难,只需实现Closeable并跟踪您输入到MDC中的键:

// MDCCloseableMap.java
public class MDCCloseableMap implements Closeable {
private final Set<String> keys;
public MDCCloseableMap(Map<String, String> entries) {
this.keys = Collections.unmodifiableSet(entries.keySet());
entries.forEach(MDC::put);
}
@Override
public void close() {
keys.forEach(MDC::remove);
}
}

你可以用同样的方式使用

log.info("This will be logged without myKeys, myValues");
Map<String, String> myEntries = Map.of("myKey1", "myValue1", "myKey2", "myValue2");
try (MDCCloseableMap ignored = new MDCCloseableMap(myEntries)) {
log.info("This will be logged with myKeys, myValues");
}
log.info("This will be logged without myKeys, myValues");

相关内容

  • 没有找到相关文章

最新更新