演变历史
Log4j
- 2001 年由 Ceki Gülcü 发布了 Log4j 并捐献给了 Apache 成为了 Apache 的顶级项目
- 优点:定义了 Logger、Appender、Level 等思想概念
- 缺点:性能低、2015年9月停止维护
- 代码:
org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(getClass());
JUL
- SUN 公司在 JDK1.4 后增加了一个包为
java.util.logging
简称 JUL 来对抗 Log4j,但是对开发造成了麻烦,相互引用的项目之间可能使用了不同的日志框架,使代码变得一片混乱 - 缺点:JUL 功能远不如 Log4j 完善,自带的 Handlers 有限,参数只接收 String,性能和可用性一般、在 JDK1.5 之后才略微有所提升
JCL
- 基于以上问题、抽象出来的一套接口层形成 JCL、JCL 会在 ClassLoader 中进行查找,默认使用 Log4j、没有则使用 JUL
- 缺点:效率低、易混乱、有可能会引发内存泄漏
- 代码:
org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(getClass())
- 缺陷代码:
log.debug("this is a debug info :" + msg);
#只能用字符串拼接
Slf4j、Logback(SpringBoot默认的)
- Log4j 的作者觉得 JCL 不好用、新写了一套接口 Slf4j 同时写了一套该接口的实现 logback
- 优点:logback 提供更高级的特性、如异步 Logger、Filter 等
- 代码:
log.debug("this is a debug info :", msg);
#解决了字符串拼接的问题
Log4j2
- Apache 宣布不再维护 Log4j 并推荐升级到 Log4j2,虽然 Log4j2 沿袭了 Log4j 的思想,但是 Log4j2 和 Log4j 完全是两码事,并不兼容。
- Log4j2 以性能著称,比 Log4j 和 Logback 有重⼤改进,继承了 Logback中 好的方面并修复了 Logback 架构中的一些固有问题。功能上,它有着和 Logback 相同的基本操作,同时又有自己独特的部分,⽐如:插件式结构、配置文件优化、异步⽇志等。
配置说明
日志级别
- all:全部日志
- trance:路径跟踪
- debug:日常调试
- info:打印重要信息
- warn:警告
- error:出现错误或问题
- 级别优先级:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
日志组件
- appender:日志输出目的地、负责日志的输出(输出到什么地方)
- logger:日志记录器、负责收集处理日志记录(如何处理日志)
- layout:日志格式化、负责对输出的日志格式化(以什么形式展现)
Logback
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="3 seconds" debug="false">
<property name="logPattern" value="logback:[ %-5level] [%date{yyyy-MM-dd
HH:mm:ss.SSS}] %logger{96} [%line] [%thread]- %msg%n"></property>
<jmxConfigurator/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<charset>UTF-8</charset>
<pattern>${logPattern}</pattern>
</encoder>
</appender>
<appender name="ROLLING_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>./logback.log</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>./logback.log.%d{yyyy-MM-dd}.zip</fileNamePattern>
<maxHistory>2</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${logPattern}</pattern>
</encoder>
</appender>
<appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
<connectionSource
class="ch.qos.logback.core.db.DriverManagerConnectionSource">
<driverClass>com.mysql.jdbc.Driver</driverClass>
<url>jdbc:mysql://172.17.0.203:3306/log?useSSL=false</url>
<user>root</user>
<password>root</password>
</connectionSource>
</appender>
<appender name="ASYNC_LOG" class="ch.qos.logback.classic.AsyncAppender">
<discardingThreshold>0</discardingThreshold>
<queueSize>3</queueSize>
<appender-ref ref="STDOUT"/>
</appender>
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLING_FILE"/>
<appender-ref ref="ASYNC_LOG"/>
</root>
</configuration>
处理器 Appender
FileAppender | 输出到本地文件 |
---|
KafkaAppender | 输出到 Kafka 队列 |
FlumeAppender | 将几个不同源的日志汇集到一处 |
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="info" monitorInterval="30">
<Properties>
<Property name="pattern">log4j2:[%-5p]:%d{YYYY-MM-dd HH:mm:ss} [%t] %c{1}:%L - %msg%n</Property>
</Properties>
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${pattern}"/>
</Console>
<File name="File" fileName="./log4j2-file.log" append="false">
<PatternLayout pattern="${pattern}"/>
</File>
<RollingFile name="RollingFile" fileName="./log4j2-rollingfile.log"
filePattern="./$${date:yyyy-MM}/log4j2-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy interval="6"
modulate="true"/>
<SizeBasedTriggeringPolicy size="1 MB"/>
</Policies>
<DefaultRolloverStrategy max="20"/>
</RollingFile>
</appenders>
<loggers>
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
<AsyncLogger name="AsyncLogger" level="trace" includeLocation="true"
additivity="true">
<appender-ref ref="Console"/>
</AsyncLogger>
<logger name="Kafka" additivity="false" level="debug">
<appender-ref ref="Kafka"/>
<appender-ref ref="Console"/>
</logger>
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration>
写法规范
logger.debug("this is debug: " + message);
logger.debug("this is json msg: {}", toJson(message));
logger.debug("this is debug:{}", message);
logger.debug("this is json msg: {}", () -> toJson(message));