如何在spring boot中使用logback和SLF4J的MDC来捕获POST请求json中的唯一跟踪?

Bra*_*avo 6 logging logback slf4j mdc spring-boot

我们正在使用:

  • 弹簧靴
  • Slf4J
  • 登录
  • ELK 栈

现在,我们要使用MDC将 POST 请求 JSON 中提供的唯一跟踪号添加到给定请求的每个日志语句中。

我在谷歌上搜索了一些博客文章,这些对我来说没什么用。

下面是logback.xml我们正在使用的

<configuration>
    <property name="PROJECT_ID" value="template-api"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
Run Code Online (Sandbox Code Playgroud)

任何人都可以提供一些关于如何完成这项工作的帮助吗?

gly*_*ing 9

您可以使用 Logback 的映射诊断上下文将唯一的跟踪号传播到每条日志消息。

这有两个部分:

  • 将您的唯一追踪号码推送至 MDC,例如MDC.put("uniqueTrackingNumber", the_unique_tracking_number);

  • 在日志语句中包含 MDC 条目。您可以通过在日志记录模式中指定它来完成此操作。因此,如果您将唯一的跟踪号存储在名为 then 的 MDC 条目中,uniqueTrackingNumber则可以通过定义如下布局将其包含在发出的日志事件中:

<layout class="ch.qos.logback.classic.PatternLayout">
    <Pattern>
        %d{yyyy-MM-dd HH:mm:ss} [%thread] [%X{uniqueTrackingNumber}] %-5level %logger{36} - %msg%n
    </Pattern>
</layout>
Run Code Online (Sandbox Code Playgroud)

文档中有更多详细信息。

我认为“唯一跟踪号”的范围仅限于请求(或通过您的应用程序的单个“流”)?如果是这样,那么您将需要确定一些节流点,您可以在其中推送 MDC 值。在 Spring Boot 世界中,这可能是一个Filter. 也许是这样的:

@Component 
public static class UniqueTrackingNumberFilter extends OncePerRequestFilter() {

    @Override
    protected abstract void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                    throws ServletException, IOException {
        // presumably this is extracted from the request (or defaulted, if not supplied)
        int uniqueTrackingNumber = ;
        MDC.put("uniqueTrackingNumber", uniqueTrackingNumber);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以扩展 LogbackMDCInsertingServletFilter以从请求中提取您想要的任何内容并将其推送到 MDC。

  • 使用 `%mdc` 打印 MDC 中存在的多个值,而无需知道每个键 (4认同)

小智 5

抱歉,没有足够的代表来撰写评论。这是基于@glytching 答案的更正确、完全有效的代码:

@Component
public class MDCFilter extends OncePerRequestFilter {

    @Autowired
    private TrackingnumberGenerator trackGen;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        MDC.put("trackingNumber", trackGen.getTrackingNumber());
        try {
            filterChain.doFilter(request, response);
        } finally {
            MDC.remove("trackingNumber");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)