关于java:Spring按业务模块输出日志到不同的文件

一、背景

在咱们开发的过程中,可能存在如下状况:
1、有些时候咱们须要调用第三方的接口,个别状况下,调用接口,咱们都会记录申请的入参和响应的。如果咱们本人零碎的日志和第三方的日志混合到一个日志文件中,那么可能查找日志就比拟麻烦了。那么咱们是否能够将第三方零碎的日志独自放到另外的文件中呢?

2、或者有些时候咱们零碎须要进行数据迁徙,如果某条数据迁徙失败了,是否独自放到一个日志文件中比拟清晰呢?

二、需要


从上图中能够看到咱们的需要比较简单

1、系统启动日志和 login 模块日志记录到 springboot-spring.log 文件中。
2、第三方业务(QQ)模块的日志记录到 springboot-qq.log文件中。
3、第三方业务(QQ)模块提供了一个login(loginName)办法,办法的入参loginName须要记录到springboot-qqLoginName.log文件中,模仿一、背景中提到的数据迁徙失败,记录失败的数据到独自的日志文件中。

三、技术实现

1、采纳的日志框架

此处应用logback来实现日志的记录,因为SpringBoot应用程序默认的就是采纳的logback来记录日志。

2、如果实现分模块、分文件记录日志

1、 编写appender,这个能够简略的了解日志须要输入到哪里。

比方:

<!-- 此处定义的日志输入到控制台 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>

    </encoder>
</appender>

<!-- 此处定义日志输入到 springboot-qq-日期.第几个.log 文件中 -->
<appender name="qqAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>logs/springboot-qq-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
    </rollingPolicy>
   
</appender>

2、如何实现模块输入日志

此处就须要咱们来配置 logger了。logger的name属性指定到具体的全包名,而后援用咱们下面定义的appender即可。

<!-- 在QQ这个包下的日志独自应用 qqAppender 来输入 -->
<logger name="com.huan.springboot.qq" level="info" additivity="false">
    <appender-ref ref="qqAppender"/>
    <appender-ref ref="stdout"/>
</logger>

配置logger,logger的name为须要独自生成文件的那个包的全包名,而后在外面援用下面定义的appender

3、如果实现将loginName输入到指定的文件

其实还是应用 logger 来实现,logger的name须要和 LoggerFactory.getLogger("此处写具体logger的name的值")

留神:
此处可能有一个坑,就是可能会失落类名,那么咱们如何进行解决呢?能够通过MDC来解决。

.... %X{CLASSNAME}#%method:%L -%msg%n
MDC.put("CLASSNAME", QQService.class.getName());
qqLoginName.info("登录用户:[{}]", loginName);

xml中应用%X{CLASSNAME},在java代码中应用MDC存入CLASSNAME的值。

四、代码实现

1、编写xml日志文件

1、编写appender

1、输入日志到控制台
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>
2、编写login模板的日志
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/springboot-spring-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
            <maxHistory>7</maxHistory>
            <maxFileSize>1MB</maxFileSize>
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
3、编写qq模板的日志
<appender name="qqAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/springboot-qq-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
            <maxHistory>7</maxHistory>
            <maxFileSize>1MB</maxFileSize>
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
4、编写qq模块loginName独自输入到文件的日志
<appender name="qqLoginNameAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/springboot-qqLoginName-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
            <maxHistory>7</maxHistory>
            <maxFileSize>1MB</maxFileSize>
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %X{CLASSNAME}#%method:%L -%msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

2、配置日志输入到具体位置

1、配置login模块
<root level="INFO">
    <appender-ref ref="stdout"/>
    <appender-ref ref="file"/>
</root>

login模块属于咱们本人的零碎模块,此处应用 root标签来配置。

2、配置qq模块
<!-- 在QQ这个包下的日志独自应用 qqAppender 来输入 -->
<logger name="com.huan.springboot.qq" level="info" additivity="false">
    <appender-ref ref="qqAppender"/>
    <appender-ref ref="stdout"/>
</logger>

此处name的值间接指定到了qq的全包名门路。

3、配置loginName独自输入到文件
<!-- 将所有的QQ登录名避免在另外的文件中 -->
<logger name="qqLoginName" level="info" additivity="false">
    <appender-ref ref="qqLoginNameAppender"/>
    <appender-ref ref="stdout"/>
</logger>

2、编写QQ模块的代码

@Component
public class QQService {

    private static final Logger log = LoggerFactory.getLogger(QQService.class);

    // getLogger("qqLoginName") 里的 qqLoginName 须要和 logback-spring.xml 中 logger的name统一,才会利用
    private static final Logger qqLoginName = LoggerFactory.getLogger("qqLoginName");

    public void login(String loginName) {
        log.info("QQ业务: 用户:[{}]开始应用QQ来登录零碎", loginName);

        MDC.put("CLASSNAME", QQService.class.getName());
        qqLoginName.info("登录用户:[{}]", loginName);
    }
}

3、编写login模块的代码

@RestController
public class LoginController {

    private static final Logger log = LoggerFactory.getLogger(LoginController.class);

    @Resource
    private QQService qqService;

    @GetMapping("login/{loginName}")
    public String login(@PathVariable("loginName") String loginName) {
        log.info("本人业务:用户:[{}]进行登录", loginName);
        qqService.login(loginName);
        return "ok";
    }
}

五、运行后果


能够看到失去了咱们冀望的后果。

六、残缺代码

https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-logger-split-file

七、一个小知识点

在SpringBoot中,如果咱们要笼罩默认的logback配置,举荐应用logback-spring.xml来配置。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理