Java Log4j 笔记

Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j,我们可以控制日志信息输送到目的地是控制台、文件、GUI 组件、甚至是套接口服务器、NT 的事件记录器、UNIX Syslog 守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

Log4j 简介

Apache Log4j 曾经是最流行的 Java 日志组件,它有两个大版本:1.x 和 2.x。log4j 1.x 早在 2012 就已经停止更新,Apache 在此之后憋了好久,然后开发出了 log4j 2.x(借鉴了不少 logback 的新理念),憋了这么久开发出来的 2.x 版本当然是很优秀的,据说比 log4j 1.x 和 logback 的性能要高出好几倍(异步)。

之前我们学习了 logback 和 slf4j,logback 和 log4j 1.x 的作者其实是同一个人,这位大佬之所以会选择开发一个新的日志框架(logback),听说是因为与 Apache 存在意见分歧,具体什么矛盾我也没仔细研究过。

SLF4J 是一个日志门面框架,而 Logback 是一个日志组件,可以将它们简单的理解为 接口 与 实现类。之所以要抽象出一个 slf4j 门面,是为了提高程序的可移植性和可定制性,使用了 slf4j 之后,如果我想换过一个底层的日志组件,比如从 logback 换为 log4j 2.x,我们只需要更换 jar 包,然后使用新的配置文件就行,而我们的程序代码是不需要做任何更改的,这符合开闭原则(对扩展开放,对修改关闭)。

而 Apache 其实也有一个日志门面框架,叫做 Jakarta Commons Logging (JCL),但是很不幸,JCL 和 log4j 1.x 都死得比较早,jcl 在 2014 年就停止更新了,而 log4j 1.x 在 2012 年停止更新。

虽然 log4j 1.x 已经停止更新这么长时间了,但是 log4j 的大名恐怕每个 Java 程序员都有所耳闻,并且目前还有很多应用都还在使用 log4j 1.x,比如 Apache Tomcat。甚至还有新的应用继续选择使用 log4j 1.x。

对于 log4j 2.x,目前暂时没有学习的计划,鉴于 log4j 1.x 还有这么多项目在用,所以本文也是主要介绍 log4j 1.2(2012 年发布的最后一个版本,使用 properties 属性文件作为配置文件格式)。

Log4j 介绍

和大多数日志组件一样,log4j 也由三个主要组件:Logger、Appender、Layout:

  • Logger:记录器,用来接收应用发出的日志请求,并进行处理;
  • Appender:追加器,用来定义日志记录应该写往哪的组件,如文件;
  • Layout:布局或者称为日志详细格式,log4j 提供类似 printf 的语法。

Logger 的层次结构
与 logback 意义,log4j 的 logger 之间也是存在层次结构的,并且它们的机构是相似的,都是按照 java 全限定类名的格式来定义父级 logger 和子级 logger,比如名为 com.zfl9 的 logger 是名为 com.zfl9.util 的 logger 的直接父级,反之,com.zfl9.util 是 com.zfl9 的直接子级。

这个树状层次结构中,有一个根节点,那就是 root logger,根记录器,就好比 Java 中的所有类的祖先类是 Object 类一样。我们可以通过 org.apache.log4j.Logger.getRootLogger() 方法来获取 root logger。

Logger 类的基本方法:

因为 logger 的名称是有意义的,并且存在层级关系,所以一个最佳实践是,使用当前类的全限定类名作为 logger 的名称,logger 的静态工厂方法提供了一个便捷方法,允许我们直接传递 java.lang.Class 对象,logger 内部会自动使用 Class 对象的 name 作为 logger 的 name,即全限定类名作为 logger 的名称。

logger 提供 6 个级别的日志记录方法(级别由低到高):

  • trace:跟踪调试
  • debug:调试
  • info:信息
  • warn:警告
  • error:错误
  • fatal:致命错误

其中 trace 和 fatal 不建议使用,所以常用的 4 个级别为:debug、info、warn、error。

与 logback 一样,log4j 的 logger 层级关系当然是有特殊用途的,不然单纯定义一个层级关系没有实际意义,这个意义就是,父 logger 上的 appender 会被子 logger 所继承。而 root logger 是最顶层的 logger,所以 root logger 上的 appender 会被所有 logger 所继承(除非明确指定不继承)。

其实除了 log4j 的配置文件格式与 logback 不同之外,其他的概念都是相辅相成的,毕竟是同一人写的。

Log4j 配置

和 logback 不同,log4j 没有所谓的默认配置,所以如果你没有提供配置文件,log4j 在运行时会报错。log4j 的配置文件格式为 *.properties java 属性文件,所谓属性文件就是一行一个 name = value 键值对而已,格式非常简单,和我们通过 JVM 运行参数 -Dprop.name=prop.value 指定是一样的。

log4j 的默认配置文件名为 log4j.properties,在运行时,log4j 会在 class path 路径中查找此文件。

root logger 配置

appender 配置

layout 配置

Log4j 例子

pom.xml

log4j.properties(普通)

Main.java

运行结果:

日志文件:

日志轮转
log4j.properties(轮转)

产生的日志文件名:

当前活动的文件为 log4j.log,已归档的文件就是后面两个。