Spring Boot:Logback MDC动态映射上下文信息到日志

在SpringBoot应用中使用Logback记录程序日志非常方便,但是随着日志量越来越大,通过查看或筛选日志定位问题也会变得越来越困难。这里提供一种将日志信息关联应用上下文(用户信息)的方式,可看做是对日志进行分组,以进一步提高查看及筛选日志的效率。

Logback框架提供了MDC(Mapped Diagnostic Context),可使日志实现对上下文的审计,下面记录将用户信息映射到日志中的过程。

1 创建工具类

创建LogbackConfigurator组件类,用于配置日志中的自定义消息(在当前案例中,此类粒度较细,直接处理用户信息,具体可根据实际情况处理需要的上下文,例如权限等其它相关信息)。类完整代码如下:


@Component
public class LogbackConfigurator {
    /**
     * 向logback日志添加用户信息
     *
     * @param userInfo
     */
    public void setUser(String userInfo) {
        MDC.put("userInfo", String.format("[%s]", userInfo));
    }

    /**
     * 从logback日志移除用户信息
     */
    public void clearUser() {
        MDC.remove("userInfo");
    }
}

2 针对请求设置上下文信息

在之前的文章<<Spring Boot:全局日志拦截处理>>中实现了全局日志拦截处理,本案例中将实现对每一个具体的请求审计上下文信息,所以对之前的全局请求拦截类GlobalRequestInterceptor添加相关MDC审计信息,如下图,类改造后完整代码如下:
在这里插入图片描述

/**
 * 全局请求拦截器
 */
@Component
public class GlobalRequestInterceptor extends HandlerInterceptorAdapter {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private final LogbackConfigurator logbackConfigurator;
    private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");

    public GlobalRequestInterceptor(LogbackConfigurator logbackConfigurator) {
        this.logbackConfigurator = logbackConfigurator;
    }

    /**
     * 请求之前被调用
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String username;
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //如果用户已登录,获取登录用户信息
        if (authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
            username = ((User) (authentication.getPrincipal())).getUsername();
        } else {
            username = authentication.getName();
        }
        this.logbackConfigurator.setUser(String.format("%s-%s", username, this.simpleDateFormat.format(new Date())));
        logger.info("=====> Request({}) start, params:{}", request.getRequestURI(), JSONObject.toJSONString(request.getParameterMap()));
        return super.preHandle(request, response, handler);
    }

    /**
     * 请求完成之后,如果需要渲染视图,则此操作在渲染视图之前
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        logger.info("=====> Request({}) end, response status:{}", request.getRequestURI(), response.getStatus());
        this.logbackConfigurator.clearUser();
        super.postHandle(request, response, handler, modelAndView);
    }
}


由于对GlobalRequestInterceptor的改造添加了LogbackConfigurator组件类,所以对应的WebConfig类添加LogbackConfigurator组件类的注入,调整如下:
在这里插入图片描述
WebConfig完整代码如下

@Configuration
public class WebConfig implements WebMvcConfigurer {

    private final GlobalRequestInterceptor globalRequestInterceptor;

    public WebConfig(GlobalRequestInterceptor globalRequestInterceptor) {
        this.globalRequestInterceptor = globalRequestInterceptor;
    }

    /**
     * 添加拦截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(this.globalRequestInterceptor);
    }
}

3 调整Logback日志配置

上面步骤已经成功将用户信息映射到了日志上下文中,再在日志配置中稍作配置即可使用。LogbackConfigurator类中将用户信息的key值设置为userInfo,所以日志配置中(当前调整的是开发环境配置logback-dev.xml)可使用userInfo获取用户信息,如下:
在这里插入图片描述

<configuration debug="true">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%yellow([%date{yyyy-MM-dd HH:mm:ss.SSS,GMT+8}]) %highlight([%-5level]) %cyan([%thread])
                %boldMagenta(%X{userInfo}) - %msg [%logger{1}] \(%file:%line\) %n
            </pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

4 最终效果

完成上面步骤后,重启应用程序,分别发送登录查询Redis两个请求(可点击 这里 查看这两个请求的源码),日志打印如下图:

在用户未登录时,请求中记录的是匿名用户,登录成功之后执行请求则会记录真实的用户信息。用户信息分为两部分:用户名请求发起时间,以查询Redis请求为例,在和此请求所有关联的日志中都会包含[crane-07:22:24.841]这个信息,可以从请求的粒度方便的查看日志。

在这里插入图片描述
在这里插入图片描述

5 总结

以上是从请求的粒度对日志进行上下文进行映射审计,也可根据实际情况从其他维度(例如多线程同用户)进行审计,提高日志筛选的便捷性。

参考

[1] 日志布局配置
[2] MDC

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`classpath:logback-spring.xml` 是一个文件路径的表达式,它表示在类路径下查找名为 `logback-spring.xml` 的文件。 在使用 Spring Boot 时,`logback-spring.xml` 文件通常用于配置日志记录器和日志输出的方式。Spring Boot 默认支持 Logback 作为日志框架,因此你可以在类路径下创建一个名为 `logback-spring.xml` 的文件来配置日志。 你可以按照以下步骤来使用 `logback-spring.xml` 文件进行日志配置: 1. 在你的项目资源文件夹(一般是 `src/main/resources`)下创建一个名为 `logback-spring.xml` 的文件。 2. 在 `logback-spring.xml` 文件中,你可以使用 Logback 的 XML 配置语法来定义日志记录器、日志输出方式、日志格式等。你可以根据自己的需求进行配置。 以下是一个简单的 `logback-spring.xml` 文件示例,用于将日志输出到控制台: ```xml <configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> </configuration> ``` 这个示例配置了一个名为 `CONSOLE` 的控制台输出日志的 appender,并定义了日志输出的格式。 3. 将 `logback-spring.xml` 文件放置在类路径下,例如将它放置在 `src/main/resources` 目录下。 当你的应用程序启动时,它将自动加载并应用 `logback-spring.xml` 文件中的配置。 希望这能帮助到你进行日志配置。如果你有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值