Java 日志框架总结
日志门面:
- Apache Commons Logging (JCL) 是 Apache Commons 的一个开源项目。官网:https://commons.apache.org/proper/commons-logging/
- SLF4J 全称为 Simple Logging Facade for Java,即 Java 简单日志门面。官网:http://www.slf4j.org/
日志门面——SLF4J
优点:
通过依赖配置,在编译期静态绑定真正的日志框架库。
What has changed in SLF4J version 2.0.0?
More visibly, slf4j-api now relies on the ServiceLoader mechanism to find its logging backend. SLF4J 1.7.x and earlier versions relied on the static binder mechanism which is no loger honored by slf4j-api version 2.0.x. More specifically, when initializing the
LoggerFactory
class will no longer search for theStaticLoggerBinder
class on the class path.Instead of “bindings” now
org.slf4j.LoggerFactory
searches for “providers”. These ship for example with slf4j-nop-2.0.x.jar, slf4j-simple-2.0.x.jar or slf4j-jdk14-2.0.x.jar.不需要使用
logger.isDebugEnabled()
来解决日志因为字符拼接产生的性能问题。SLF4J 的方式是使用{}
作为字符串替换符。提供了很多桥接方案,以便灵活替换日志库。
缺点:
旧版不支持 Lambda 表达式(slf4j-api-2.0.0-alpha 支持但还未 GA)。但日志框架 Log4j 2.4 及以上版本支持 Java 8 Lambda,参考 1、2,例如:
1
logger.debug("This {} and {} with {} ", () -> this, () -> that, () -> compute());
SLF4J bindings
http://www.slf4j.org/manual.html#swapping
Logback
推荐使用 SLF4J bound to logback-classic 的经典组合:
1 | <dependency> |
传递依赖如下:
1 | ch.qos.logback:logback-classic:jar:1.2.3:compile |
Log4j 2.x
https://logging.apache.org/log4j/2.x/
需引入适配层依赖:
1 | <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl --> |
传递依赖如下:
1 | org.apache.logging.log4j:log4j-slf4j-impl:jar:2.16.0:compile |
参考:
- 《试试这款性能最强的日志框架 Log4j 2》
- <Reasons to prefer logback over log4j 1.x>
- 《突发!Log4j 2 爆“核弹级”漏洞,Flink、Kafka 等至少十多个项目受影响》
- 《Log4j 2 再发新版本 2.16.0,完全删除 Message Lookups 的支持,加固漏洞防御!》
Log4j 1.x
https://logging.apache.org/log4j/1.2/
On August 5, 2015 the Logging Services Project Management Committee announced that Log4j 1.x had reached end of life.
需引入适配层依赖:
1 | <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> |
传递依赖如下:
1 | org.slf4j:slf4j-log4j12:jar:1.7.32:compile |
java.util.logging (JUL)
需引入适配层依赖:
1 | <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 --> |
传递依赖如下:
1 | org.slf4j:slf4j-jdk14:jar:1.7.32:compile |
日志框架——Logback
Configuration
https://logback.qos.ch/manual/configuration.html
Logback 配置文件样例:
1 |
|
Appenders
有三种 Appenders:
- Logback 官方提供的 Appenders。
- 第三方提供的 Appenders(logstash、…)。
- 自定义 Appenders。
官方 Appenders
Logback 官方提供的 Appenders 如下:http://logback.qos.ch/manual/appenders.html
其中,常用的两个 Appender 继承结构如下:
ch.qos.logback.core.ConsoleAppender
ch.qos.logback.core.rolling.RollingFileAppender
其中,ch.qos.logback.core.rolling.RollingFileAppender
可选的策略类如下:
第三方 Appenders
https://github.com/logstash/logstash-logback-encoder
Provides logback encoders, layouts, and appenders to log in JSON and other formats supported by Jackson.
自定义 Appenders
通过自定义 Appenders,可以将日志输出到任意位置,如 MongoDB、Kafka 等服务。
下面演示一个简单的同步 Appender,如需异步 Appender,参考这里。
首先,新建 Appender,继承自抽象类:
代码如下:
1 | import ch.qos.logback.classic.spi.ILoggingEvent; |
最后,验证 MongoDB 数据。
Encoders & Layouts
https://logback.qos.ch/manual/encoders.html
https://logback.qos.ch/manual/layouts.html
Logback 提供的 ch.qos.logback.core.encoder.Encoder
和 ch.qos.logback.core.Layout
的默认实现如下:
一般有几种使用组合方式:
自定义 Pattern 格式
基于自定义 Pattern 格式,直接使用 ch.qos.logback.classic.encoder.PatternLayoutEncoder
即可:
1 | <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
还可以输出扩展信息,例如 %X{traceId}
。
预定义格式
基于预定义格式,需要使用 ch.qos.logback.core.encoder.LayoutWrappingEncoder
,并搭配相应 Layout
实现。例如输出成 HTML 格式:
1 | <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
Mapped Diagnostic Contexts (MDC)
https://logback.qos.ch/manual/mdc.html
To uniquely stamp each request, the user puts contextual information into the
MDC
, the abbreviation of Mapped Diagnostic Context.The
MDC
class contains only static methods. It lets the developer place information in a diagnostic context that can be subsequently retrieved by certain logback components. TheMDC
manages contextual information on a per thread basis. Typically, while starting to service a new client request, the developer will insert pertinent contextual information, such as the client id, client’s IP address, request parameters etc. into theMDC
. Logback components, if appropriately configured, will automatically include this information in each log entry.Please note that MDC as implemented by logback-classic assumes that values are placed into the MDC with moderate frequency. Also note that a child thread does not automatically inherit a copy of the mapped diagnostic context of its parent.
Logback leverages SLF4J API:
MDC And Managed Threads
https://logback.qos.ch/manual/mdc.html#managedThreads
MDCInsertingServletFilter
https://logback.qos.ch/manual/mdc.html#mis
例子
一、创建 MDCUtils
1 | import lombok.experimental.UtilityClass; |
二、在合适的位置设置上下文:
- 在 http 接口的拦截器
- 在定时任务执行之前
- …
代码如下:
1 | try (MDC.MDCCloseable mdc = MDCUtils.addTraceId(...)) { |
三、选择合适的 Appender 并加以配置,参考 Logback 配置文件样例。
参考
https://github.com/logstash/logstash-logback-encoder