在阿里最新的Java开发手册(泰山版)中,对日志的记录有一条强制的要求:
【强制】应用中的扩展日志(如打点、临时监控、访问日志等)命名方式:appName_logType_logName.log。logType:日志类型,如stats/monitor/access等;logName:日志描述。这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查找。
说明:推荐对日志进行分类,如将错误日志和业务日志分开存放,便于开发人员查看,也便于通过日志对系统进行及时监控。
如何进行多业务日志文件配置呢?可参考文章:转自logback多业务日志文件配置
另:logback配置多个日志文件
背景:
一般业务并不复杂的项目,logback日志只需配置一种,即最高级就行,但如果项目业务种类不止一个,且需要按类别打印日志进行数据分析的地方较多,一种logger当然远远不够!在此我们研究下如何进行多业务日志配置吧!
一、logback配置文件
在 resources
根目录下创建 logback.xml
文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--自定义控制台日志格式-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder charset="UTF-8">
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %level [%thread] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--系统INFO级别日志-滚动记录日志-->
<appender name="SYS_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值-->
<File>D:/log/yj-test/sys_info.log</File>
<!--如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。-->
<append>true</append>
<!--级别过滤器(LevelFilter),此处只打INFO级别的日志-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<!--下面2个属性表示匹配规定level的接受打印,不匹配的(即非INFO)拒绝打印-->
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--设置滚动文件规则,如果直接使用 %d,默认格式是 yyyy-MM-dd-->
<fileNamePattern>D:/log/yj-test/sys_info.log.%d</fileNamePattern>
<!--保留30天的日志-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %level [%thread] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--系统ERROR级别日志-滚动记录日志-->
<appender name="SYS_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>D:/log/yj-test/sys_error.log</File>
<append>true</append>
<!--此处只打ERROR级别的日志-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>D:/log/yj-test/sys_error.log.%d</fileNamePattern>
<maxHistory>12</maxHistory>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %level [%thread] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--不同业务逻辑的日志打印到不同文件,见下面2种业务日志-->
<!--业务business-1日志-->
<appender name="business_1_Appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>D:/log/yj-test/b1.log</File>
<append>true</append>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>D:/log/yj-test/b1.log.%d</fileNamePattern>
<maxHistory>12</maxHistory>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %level [%thread] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!--业务business-2日志-->
<appender name="business_2_Appender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>D:/log/yj-test/b2.log</File>
<append>true</append>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>D:/log/yj-test/b2.log.%d</fileNamePattern>
<maxHistory>12</maxHistory>
</rollingPolicy>
<encoder charset="UTF-8">
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %level [%thread] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- additivity属性为false,表示此logger的打印信息不再向上级传递(注:该值默认为true,logger的日志信息会依次向上级传递,最高级logger为root,如果不加则至少打印2次,本身一次,root一次)-->
<logger name="business_1" additivity="false" level="INFO">
<appender-ref ref="business_1_Appender"/>
</logger>
<logger name="business_2" additivity="false" level="INFO">
<appender-ref ref="business_2_Appender"/>
</logger>
<!--info和error分开打印,注:ERROR > WARN > INFO > DEBUG > TRACE-->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="SYS_INFO"/>
<appender-ref ref="SYS_ERROR"/>
</root>
</configuration>
我把相关配置参数都详细注释含义了,相信大家都能看懂,重点是两个业务business1、2的日志配置!
二、编写测试类
我们一般都是通过 LoggerFactory.getLogger(xxx.class)
方法来得到日志对象,但此处我们需要得到配置文件里自定义的业务日志对象!
源码:
该方法不仅可以根据 类名.class
来获取日志对象,也可根据 logger name
获取!
创建 logger name 枚举类:
package com.yj.springboot.test;
/**
* @Author: yuanj
* @Date: 2018/6/23 16:07
*/
public enum LogNameEnum {
BUSINESS_1("business_1"),
BUSINESS_2("business_2");
private String logName;
LogNameEnum(String logName) {
this.logName = logName;
}
public String getLogName() {
return logName;
}
public void setLogName(String logName) {
this.logName = logName;
}
}
创建测试 controller:
package com.yj.springboot.test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: yuanj
* @Date: 2018/6/23 16:06
*/
@RestController
public class TestLogbackController {
private static final Logger business_1_log = LoggerFactory.getLogger(LogNameEnum.BUSINESS_1.getLogName());
private static final Logger business_2_log = LoggerFactory.getLogger(LogNameEnum.BUSINESS_2.getLogName());
@RequestMapping("/log")
public String testLogback(){
for(int i = 1;i<10;i++){
business_1_log.info("业务日志:business_1====="+i);
business_2_log.info("业务日志:business_2====="+i);
}
return "ok";
}
}
三、测试结果
我们运行项目后可以在 logback.xml
里定义的日志文件路径里看到自动生成了4个日志文件:
在浏览器上发送请求:localhost:8080/log
,可以看到 b1.log
和 b2.log
出现日志内容:
b1.log:
b2.log:
至此,成功实现多日志文件配置!