在项目中如果把所有的日志都记到一个 info.log 分析起来会很麻烦,中间夹着不同业务产生的日志,所以我们需要将不同的业务日志拆分到不同的文件中,便于日志分析。
一般日志文件的命名为:xxx.info.log 、xxx.error.log,如下图
一般 error 的日志我们重点关注。如果业务日志文件多了,找起来比较麻烦(当然也可以用 搜索 *.error.log)
我们在项目中会将 error 放在开头(也可以按文件夹来划分,比如将 api 建成一个文件夹)这样查找起来比较方便,如下图
在logback.xmp中,根据业务合理分析定义日志文件保存规则
然后再按 领域、业务,命名业务日志文件,如不同厂家的接口,可以命名为:api_厂商_业务_info.log ,
以下基于 LogBack 日志类实现的demo , LogBack 是 log4j 的升级版, 基于 slf4j 的实现,(log4j、slf4j、logback 是同一作者)
log4j2 是Apache 的产品,和 log4j 不是一个人写的。名字有点坑
代码如下
LogTests.java
package com.iron.demo; import com.iron.demo.utility.LogFileName; import com.iron.demo.utility.LoggerUtils; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class LogTests { Logger LOG_API_HIS_PRESCRIPTION = LoggerUtils.Logger(LogFileName.LOG_API_HIS_PRESCRIPTION); Logger LOG_API_IRON_PRESCRIPTION = LoggerUtils.Logger(LogFileName.LOG_API_IRON_PRESCRIPTION); @Test public void testBusinessLog() throws Exception { LOG_API_HIS_PRESCRIPTION.info("HIS 接口产生的相关日志..."); for (int i = 0; i < 5; i++) { LOG_API_IRON_PRESCRIPTION.info("Iron 设备相关的业务日志..."+i); } LOG_API_HIS_PRESCRIPTION.error("HIS 接口产生的【错误】日志..."); LOG_API_IRON_PRESCRIPTION.error("Iron 接口产生的【错误】日志..."); } }
LogFileName.java
package com.iron.demo.utility; public enum LogFileName { //配置到logback.xml中的logger name="apiHis" LOG_API_HIS_PRESCRIPTION("apiHis"), LOG_API_IRON_PRESCRIPTION("apiIron"); private String logFileName; LogFileName(String fileName) { this.logFileName = fileName; } public String getLogFileName() { return logFileName; } public void setLogFileName(String logFileName) { this.logFileName = logFileName; } public static LogFileName getAwardTypeEnum(String value) { LogFileName[] arr = values(); for (LogFileName item : arr) { if (null != item && item.logFileName == null && !(item.logFileName.trim().isEmpty())) { return item; } } return null; } }
LoggerUtils.java
package com.iron.demo.utility; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LoggerUtils { /** * 传统默认的记录方式 * @param clazz * @param <T> * @return */ public static <T> Logger Logger(Class<T> clazz) { return LoggerFactory.getLogger(clazz); } /** * 记录到指定的文件下 * * @param desc 日志文件名称 * @return */ public static Logger Logger(LogFileName desc) { return LoggerFactory.getLogger(desc.getLogFileName()); } }
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> <appender name="SYS_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${catalina.base}/logs/info.log</File> <append>true</append> <!--过滤器,只打INFO级别的日志,日志文件最多保留15天(如果是按天滚动)--> <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>${catalina.base}/logs/info.log.%d{yyyy-MM-dd}</fileNamePattern> <maxHistory>15</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> <appender name="SYS_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${catalina.base}/logs/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>${catalina.base}/logs/error.log.%d{yyyy-MM-dd}</fileNamePattern> <maxHistory>15</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> <!--不同业务产生的日志打印到不同文件中--> <appender name="API_HIS_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${catalina.base}/logs/api_his_info.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>${catalina.base}/logs/api_his_info.log.%d{yyyy-MM-dd}</fileNamePattern> <maxHistory>15</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> <appender name="API_HIS_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${catalina.base}/logs/error_api_his.log</File> <append>true</append> <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>${catalina.base}/logs/error_api_his.log.%d{yyyy-MM-dd}</fileNamePattern> <maxHistory>15</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> <appender name="API_IRON_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${catalina.base}/logs/api_iron_info.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>${catalina.base}/logs/api_iron_info.log.%d{yyyy-MM-dd}</fileNamePattern> <maxHistory>15</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> <appender name="API_IRON_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${catalina.base}/logs/error_api_iron.log</File> <append>true</append> <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>${catalina.base}/logs/error_api_iron.log.%d{yyyy-MM-dd}</fileNamePattern> <maxHistory>15</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> <!--设置 com.iron.demo 包空间下面的日志 level 显示--> <logger name="com.iron.demo" level="INFO"/> <!-- 不同的业务逻辑日志打印到指定文件中 && info 和 error 分开--> <logger name="apiHis" additivity="false" level="INFO"> <appender-ref ref="API_HIS_INFO"/> <appender-ref ref="API_HIS_ERROR"/> </logger> <logger name="apiIron" additivity="false" level="INFO"> <!--打到控制台--> <appender-ref ref="CONSOLE"/> <appender-ref ref="API_IRON_INFO"/> <appender-ref ref="API_IRON_ERROR"/> </logger> <!--系统级的日志(默认) info和error分开打印--> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="SYS_INFO"/> <appender-ref ref="SYS_ERROR"/> </root> </configuration>