簡體   English   中英

SpringBoot MDC 只針對下一個日志

[英]SpringBoot MDC only for the next log

請關於 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 ,它允許您利用 try-with-resources 塊:

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");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM