流行的日志框架
- JUL,java.util.logging包下的,是Java原生日志框架
- Log4j,Apache的一个开源项目
- Logback,由Log4j之父做的另一个开源项目,业界中称作log4j后浪,一个可靠、通用且灵活的java日志框架
- Log4j2,Log4j官方的第二个版本,各个方面都是与Logback及其相似,具有插件式结构、配置文件优化等特征,Spring Boot1.4版本以后就不再支持log4j,所以第二个版本应运而生
- 日志门面技术: JCL、 SLF4J,用于整合不同日志框架的API,可以更换不同的日志框架而不需要修改代码。
JUL
JUL(Java Util Logging)是java原生的日志框架,使用时不需要另外引用第三方的类库,相对其他的框架使用方便,学习简单,主要是使用在小型应用中。

组成:
- Logger:日志记录器,用于记录日志
- Handler:日志处理器,用于输出日志
- Filter:过滤器,提供了日志级别之外更细粒度的控制
- Formatter:格式化输出
原理:
- 系统启动时,读取默认的logger配置文件,初始化一个单例的LogManager,负责管理所有的Logger,每次用
Logger.getLogger("org.example.xxx")
获取一个logger都会在LogManager里注册。 - 不同的logger之间是有父子关系的,比如
Logger.getLogger("org.example")
是Logger.getLogger("org.example.xxx")
的父logger,那么子logger的日志会发送给父logger的hangler,默认RootLogger的名字是一个空字符串 - logger和hangler都可以设置日志级别,不同时,取高级别的输出,默认RootLogger的级别是INFO,可以在默认的配置文件中看到
- 默认有一个RootLogger,它有一个ConsoleHandler,RootLogger是所有logger的父logger,如果没有
log1.setUseParentHandlers(false)
,日志都会发送给RootLogger的ConsoleHandler
Log4j
Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
组成:
- Loggers:日志记录器,负责收集处理日志记录,实例的命名就是类的全限定名,Logger的名字大小写敏感,其命名有继承机制。Log4J中有一个特殊的logger叫做”root”,他是所有logger的根,可以用Logger.getRootLogger()方法获取。
- Appenders:类似Handler,但提供了更强大的功能,比如允许把日志输出到不同的地方,如控制台(Console)、文件(Files)等,可以根据天数或者文件大小产生新的文件,可以以流的形式发送到其它地方等等。常用Appender:
- ConsoleAppender 将日志输出到控制台
- FileAppender 将日志输出到文件中
- DailyRollingFileAppender 将日志输出到一个日志文件,并且每天输出到一个新的文件
- RollingFileAppender 将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件
- JDBCAppender 把日志信息保存到数据库中
- Layouts:Log4j可以在Appenders的后面附加Layouts来完成这个功能。Layouts提供四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式。常用Layouts:
- HTMLLayout 格式化日志输出为HTML表格形式
- SimpleLayout 简单的日志输出格式化,打印的日志格式如默认INFO级别的消息
- PatternLayout 最强大的格式化组件,可以根据自定义格式输出日志,如果没有指定转换格式, 就是用默认的转换格式
格式说明:
%m 输出代码中指定的日志信息
%p 输出优先级,及 DEBUG、INFO 等
%n 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n")
%r 输出自应用启动到输出该 log 信息耗费的毫秒数
%c 输出打印语句所属的类的全名
%t 输出产生该日志的线程全名
%d 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日 HH:mm:ss}
%l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:Test.main(Test.java:10)
%F 输出日志消息产生时所在的文件名称
%L 输出代码中的行号
%% 输出一个 "%" 字符
可以在 % 与字符之间加上修饰符来控制最小宽度、最大宽度和文本的对其方式。如:
%5c 输出category名称,最小宽度是5,category5,就会将左边多出的字符截掉,30字符,就从左边交远销出的字符截掉
JCL
JCL(Jakarta Commons Logging)是Apache提供的一个通用日志API。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的jul, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。默认会使用JUL日志框架做日志的记录
使用它的好处就是,代码依赖是common-logging而非log4j的API, 避免了和具体的日志API直接耦合,在有必要时,可以更改日志实现的第三方库。
JCL 有两个基本的抽象类:
- Log:日志记录器
- LogFactory:日志工厂(负责创建Log实例)
SLF4j
- 门面模式
门面模式(Facade Pattern),也称之为外观模式,其核心为:外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用。
外观模式主要是体现了Java中的一种好的封装性。更简单的说,就是对外提供的接口要尽可能的简单。 - 日志门面
前面介绍的几种日志框架,每一种日志框架都有自己单独的API,要使用对应的框架就要使用其对应的API,这就大大的增加应用程序代码对于日志框架的耦合性。
为了解决这个问题,就是在日志框架和应用程序之间架设一个沟通的桥梁,对于应用程序来说,无论底层的日志框架如何变,都不需要有任何感知。只要门面服务做的足够好,随意换另外一个日志框架,应用程序不需要修改任意一行代码,就可以直接上线。[En]
In order to solve this problem, it is necessary to build a bridge between the logging framework and the application. For the application, no matter how the underlying logging framework changes, it does not need any awareness. As long as the facade service is good enough, feel free to change another logging framework, and the application can go online without modifying any line of code.
- 常见日志框架及门面
常见的日志实现:JUL、log4j、logback、log4j2
常见的日志门面 :JCL、slf4j
出现顺序 :log4j –>JUL–>JCL–> slf4j –> logback –> log4j2 - slf4j
SLF4j(Simple Logging Facade For Java)主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如log4j和logback等。 当然slf4j自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。所以我们可以得出SLF4J最重要的两个功能就是对于日志框架的绑定以及日志框架的桥接。
官方网站: https://www.slf4j.org/ - slf4j桥接技术
通常,我们依赖的某些组件依赖于SLF4J以外的日志API。我们可能还假设这些组件在不久的将来不会切换到SLF4J。为了处理这种情况,SLF4J附带了几个桥接模块,这些模块会将对log4j,JCL和java.util.logging API的调用重定向为行为,就好像是对SLF4J API进行的操作一样。
使用:
- 加入slf4j核心依赖,再加入其它日志实现框架即可。如 slf4j + logback, slf4j + log4j + 适配器slf4j-log4j12
- 如果现有系统使用的是其它日志框架,也可以使用 slf4j + 桥接器实现不改变现有代码就可以使用slf4j
slf4j+log4j2:(适配器包含了slf4j依赖和log4j2的核心依赖)
org.apache.logging.log4j
log4j-slf4j-impl
2.17.1
Logback
Logback是由log4j创始人设计的又一个开源日志组件。
Logback当前分成三个模块:logback-core,logback- classic和logback-access。
logback-core是其它两个模块的基础模块。
logback-classic是log4j的一个改良版本。此外logback-classic完整实现SLF4J API。使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。
logback-access访问模块与Servlet容器集成提供通过Http来访问日志的功能。
组成:
- Logger: 日志的记录器,主要用于存放日志对象,也可以定义日志类型、级别。
- Appender:用于指定日志输出的目的地,目的地可以是控制台、文件、数据库等等。
- Layout: 负责把事件转换成字符串,格式化的日志信息的输出。
- 在Logback中Layout对象被封装在encoder中。也就是说我们未来使用的encoder其实就是Layout
Logback提供了3种配置文件
- logback.groovy
- logback-test.xml
- logback.xml
如果都不存在则采用默认的配置
日志输出格式:
%-10level 级别 案例为设置10个字符,左对齐
%d{yyyy-MM-dd HH:mm:ss.SSS} 日期
%c 当前类全限定名
%M 当前执行日志的方法
%L 行号
%thread 线程名称
%m或者%msg 信息
%n 换行
Log4j2
Apache Log4j 2是对Log4j的升级,它比其前身Log4j 1.x提供了重大改进,并提供了Logback中可用的许多改进,同时修复了Logback架构中的一些问题。被誉为是目前最优秀的Java日志框架。
- 自动重新加载配置
与Logback一样,Log4j2可以在修改时自动重新加载其配置。与Logback不同,它会在重新配置发生时不会丢失日志事件。 - 高级过滤
与Logback一样,Log4j2支持基于Log事件中的上下文数据,标记,正则表达式和其他组件进行过滤。
此外,过滤器还可以与记录器关联。与Logback不同,Log4j2可以在任何这些情况下使用通用的Filter类。 - 插件架构
Log4j使用插件模式配置组件。因此,您无需编写代码来创建和配置Appender,Layout,Pattern Converter等。在配置了的情况下,Log4j自动识别插件并使用它们。 - 无垃圾机制
在稳态日志记录期间,Log4j2 在独立应用程序中是无垃圾的,在Web应用程序中是低垃圾。这减少了垃圾收集器的压力,并且可以提供更好的响应性能。
目前市面上最主流的日志门面就是SLF4J,虽然Log4j2 也是日志门面,因为它的日志实现功能非常强大,性能优越。所以我们一般情况下还是将 Log4j2 看作是日志的实现
SLF4j + Log4j2 的组合,是市场上最强大的日志功能实现方式,绝对是未来的主流趋势。 - 异步日志是log4j2最大的特色,其性能的提升主要也是从异步日志中受益。
Log4j2提供了两种实现日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应前面我们说的Appender组件和Logger组件。注意这是两种不同的实现方式,在设计和源码上都是不同的体现 - AsyncAppender方式
是通过引用别的Appender来实现的,当有日志事件到达时,会开启另外一个线程来处理它们。需要注意的是,如果在Appender的时候出现异常,对应用来说是无法感知的。 AsyncAppender应该在它引用的Appender之后配置,默认使用 java.util.concurrent.ArrayBlockingQueue实现而不需要其它外部的类库。 当使用此Appender的时候,在多线程的环境下需要注意,阻塞队列容易受到锁争用的影响,这可能会对性能产生影响。这时候,我们应该考虑使用无锁的异步记录器(AsyncLogger)。 - AsyncLogger方式
AsyncLogger才是log4j2实现异步最重要的功能体现,也是官方推荐的异步方式。它可以使得调用Logger.log返回的更快。你可以有两种选择:全局异步和混合异步。- 全局异步:所有的日志都异步的记录,在配置文件上不用做任何改动,只需要在jvm启动的时候增加一个参数即可实现。
- 混合异步:你可以在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活。虽然Log4j2提供以一套异常处理机制,可以覆盖大部分的状态,但是还是会有一小部分的特殊情况是无法完全处理的,比如我们如果是记录审计日志(特殊情况之一),那么官方就推荐使用同步日志的方式,而对于其他的一些仅仅是记录一个程序日志的地方,使用异步日志将大幅提升性能,减少对应用本身的影响。
混合异步的方式需要通过修改配置文件来实现,使用AsyncLogger标记配置。
总结
- 日志框架:jul,log4j,logback, log4j2
- 日志门面:jcl,slf4j
- springboot默认使用slf4j + logback,当前性能最强是slf4j + log4j2
- log4j使用配置文件log4j.properties
- logback使用配置文件logback.xml
- log4j2使用配置文件log4j2.xml、log4j2.component.properties(配置全局异步)
官网: - log4j:https://logging.apache.org/log4j/2.x/
- logback:https://logback.qos.ch/
- slf4j:https://www.slf4j.org/
Original: https://www.cnblogs.com/bingmous/p/15786789.html
Author: Bingmous
Title: Java日志框架
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/117372/
转载文章受原作者版权保护。转载请注明原作者出处!