Java 日志处理框架
日志生态
在 Java 生态体系中。关于日志输出,主 要有两类工具。
- 一类是日志框架,主要用来进行日志的输出的,比如输出到哪个文件,日志格式 如何等。
- 另外一类是日志门面,主要一套通用的 API,用来屏蔽各个日志框架之间的 差异的。
用途
- 线上问题追踪,
- 错误排查,
- 基于 日志的业务逻辑统计分析等都离不日志
日志规约
日志API的使用
【强制】应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架(SLF4J、JCL—Jakarta Commons Logging)中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
说明:日志框架(SLF4J、JCL—Jakarta Commons Logging)的使用方式(推荐使用 SLF4J)
使用 SLF4J:
所以,对于 Java 工程师来说,关于日志工具的使用,最佳实践就是在应用中使 用如 Log4j + SLF4J 这样的组合来进行日志输出。
这样做的最大好处,就是业务层的开发不需要关心底层日志框架的实现及细节, 在编码的时候也不需要考虑日后更换框架所带来的成本。这也是门面模式所带来的 好处。
综上,请不要在你的 Java 代码中出现任何 Log4j 等日志框架的 API 的使用,而 是应该直接使用 SLF4J 这种日志门面。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Test.class);
使用 JCL:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
private static final Log log = LogFactory.getLog(Test.class);
其他注意事项
项目上线之前需要把所有I/O操作(输出语句、日志输出、e.printstacktrace)关闭
Log4j日志框架
Log4j 的日志级别
在 Log4j 中建议只使用 DEBUG、INFO、WARN、ERROR 四个日志级别。
- DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打 印一些运行信息。
- INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重 要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避 免打印过多的日志。
- WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一 些提示。
- ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息, 如果不想输出太多的日志,可以使用这个级别。
Log4j2使用
引入依赖
(最美天气)引入依赖<!-- 实现对 SLF4J + Log4j2 的依赖的引入 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- log4j 新版本依赖 start-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.0</version>
</dependency>
<!--不加下面这个依赖mybatis sql日志打印有问题-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.0</version>
<scope>compile</scope>
</dependency>
<!-- 去除 SpringBoot自带Log -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- log4j 新版本依赖 end-->
官方配置文档resoutces
目录下新建log4j2.xml
文件
配置文件节点解析
比较完整的log4j2.xml
```xml <?xml version=”1.0” encoding=”UTF-8”?>
<!--先定义所有的appender-->
<appenders>
<!--console节点:输出控制台的配置,
name:指定appender节点名称
target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT.
PatternLayout:输出格式,不设置默认为:%m%n.-->
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
</console>
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用-->
<!--File节点用来定义输出到指定位置的文件的Appender.
name:指定Appender的名字.
fileName:指定输出日志的目的文件带全路径的文件名.
PatternLayout:输出格式,不设置默认为:%m%n.—>
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<!--RollingFile节点用来定义超过指定大小自动删除旧的创建新的的Appender.
name:指定Appender的名字.
fileName:指定输出日志的目的文件带全路径的文件名.
PatternLayout:输出格式,不设置默认为:%m%n.
filePattern:指定新建日志文件的名称格式.
Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志.
TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am.
SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小.
DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。—>
<RollingFile name="RollingFileWarn" fileName="${sys:user.home}/logs/warn.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${sys:user.home}/logs/error.log"
filePattern="${sys:user.home}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.
AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity=”false”只在自定义的Appender中进行输出。—>
`zmCacheManager:log4j2.xml`配置
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!-- status log4j2内部日志级别 -->
<configuration status="INFO" monitorInterval="30">
<!-- 全局参数 -->
<Properties>
<Property name="pattern">%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %c{1}:%L -%m%n</Property>
<Property name="displayName" >zmCacheManager</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT" follow="true">
<PatternLayout>
<pattern>${pattern}</pattern>
</PatternLayout>
</Console>
<!-- 文件 每次运行程序会自动清空,由append属性决定 -->
<RollingFile name="error" fileName="logs/${displayName}_error.log"
filePattern="logs/${displayName}_error.log.%i">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<Filters>
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout>
<pattern>%d %p %c{1} %m%n</pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<DefaultRolloverStrategy max="3"/>
</RollingFile>
<!--${sys:catalina.home} 指向tomcat安装目录-->
<!--输出到文件 用来定义超过指定大小自动删除旧的创建新的的Appender.-->
<RollingFile name="RollingInfoFile" fileName="logs/${displayName}_info.log"
filePattern="logs/${displayName}_info.log.%i">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<Filters>
<ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout>
<pattern>%d %p %c{1} %m%n</pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<DefaultRolloverStrategy max="3"/>
</RollingFile>
${sys:catalina.home} 指向tomcat安装目录
输出到文件 用来定义超过指定大小自动删除旧的创建新的的Appender.
<RollingFile name="debug" fileName="logs/${displayName}_debug.log"
filePattern="logs/${displayName}_debug.log.%i">
<Filters>
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<PatternLayout>
<pattern>%d %p %c{1} %m%n</pattern>
</PatternLayout>
<Policies>
<OnStartupTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="=100 MB"/>
</Policies>
<DefaultRolloverStrategy max="3"/>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="org.springframework" level="INFO" />
<Logger name="RollingInfoFile" level="INFO" additivity="false" />
<Logger name="debug" level="DEBUG" additivity="false" />
<Root level="DEBUG">
<AppenderRef ref="console"/>
<AppenderRef ref="error"/>
<AppenderRef ref="RollingInfoFile"/>
<AppenderRef ref="debug"/>
</Root>
</Loggers>
</configuration>