最新消息:天气越来越冷,记得加一件厚衣裳

一篇文章学会使用Log4j

Java w3sun 1412浏览 0评论

前言

Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的,现在则是Apache软件基金会的一个项目。 log4j是几种Java日志框架之一。Gülcü此后开创了SLF4J和Logback项目,意图成为log4j的继任者,本站后续将进行介绍。log4j团队创建了log4j的继任者,版本号为2.0的新版本。log4j 2.0着重于log4j 1.2、1.3、java.util.logging和logback中的问题,并解决这些框架中的架构问题。官网为:直达。

基本上在Spark、Flink中默认都采用的是Log4j,当然用户也可以选择其他类型的日志记录框架。先上一个Demo热热身。

Demo

新建一个maven项目,依赖中引入需要的jar包配置:

<dependencies>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

随后需要在resources文件夹下新建一个log4j.properties文件并引入以下配置(配置中各配置项含义后续讲解):

log4j.rootLogger=DEBUG,Console,File
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#File
log4j.appender.File=org.apache.log4j.FileAppender
log4j.appender.File.File=/Users/w3sun/github/log4j/log_file.log
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

依赖和配置完事后可以编写代码Demo了,Log4j提供了丰富的日志输出级别,常用的有四种,严重程度依次为ERROR,WARN,INFO,DEBUG依次递减。

import org.apache.log4j.Logger;
import org.junit.Test;

/**
 * @author: w3sun
 * @date: 2017/12/01 12:48
 * @description:
 */
public class Log4jTest {
  private static final Logger logger = Logger.getLogger(Log4jTest.class);

  @Test
  public void testLogger() {
    logger.trace("---trace level---");
    logger.info("---info level---");
    logger.debug("----debug level---");
    logger.warn("---warn level---");
    logger.error("---error level---");
    logger.fatal("---fatal level---");
  }
}

运行结果:

2017-12-01 11:36:36,159 [main] INFO  [Log4jTest] - ---info level---
2017-12-01 11:36:36,159 [main] DEBUG [Log4jTest] - ----debug level---
2017-12-01 11:36:36,159 [main] WARN  [Log4jTest] - ---warn level---
2017-12-01 11:36:36,160 [main] ERROR [Log4jTest] - ---error level---
2017-12-01 11:36:36,160 [main] FATAL [Log4jTest] - ---fatal level---

由于设置了输出文件,因此在日志文件log_file.log也会存储有日志信息。关于其中详细参数设置现在慢慢道来。

日志级别配置

如上文提到到,Log4J支持丰富的日志打印级别,详细如下:

级别 描述
OFF 最高级别,用于关闭日志记录。
FATAL 导致应用程序提前终止的严重错误。一般这些信息将立即呈现在状态控制台上。
ERROR 其他运行时错误或意外情况。一般这些信息将立即呈现在状态控制台上。
WARN 使用已过时的API,API的滥用,潜在错误,其他不良的或意外的运行时的状况(但不一定是错误的)。一般这些信息将立即呈现在状态控制台上。
INFO 令人感兴趣的运行时事件(启动/关闭)。一般这些信息将立即呈现在状态控制台上,因而要保守使用,并保持到最低限度。
DEBUG 流经系统的详细信息。一般这些信息只记录到日志文件中。
TRACE 最详细的信息。一般这些信息只记录到日志文件中。

log4j.properties中使用Log4j 根配置语法定义了日志输出级别和日志输出的路径:

log4j.rootLogger = [ level ] , appenderName, appenderName, …

Log4j支持将指定级别的日志信息输出到指定的一个或者多个位置,比如控制台或者日志文件。由于上文中定义的日志级别是DEBUG因此会输出DEBUG及以上级别的日志信息,DEBUG以下级别(TRACE)的日志信息将不会输出。同理如果设置日志输出级别为INFO,则只会输出INFO及以上级别的日志信息:

2017-12-01 11:58:00,894 [main] INFO  [Log4jTest] - ---info level---
2017-12-01 11:58:00,895 [main] WARN  [Log4jTest] - ---warn level---
2017-12-01 11:58:00,895 [main] ERROR [Log4jTest] - ---error level---
2017-12-01 11:58:00,895 [main] FATAL [Log4jTest] - ---fatal level---

同理,如果设置日志输出级别为WARN,则不会输出WARN级别以下的日志信息:

2017-12-01 11:59:37,536 [main] WARN  [Log4jTest] - ---warn level---
2017-12-01 11:59:37,537 [main] ERROR [Log4jTest] - ---error level---
2017-12-01 11:59:37,537 [main] FATAL [Log4jTest] - ---fatal level---

日志输出目的地Appender配置

从配置文件中可以看出,本文指定了两个输出路径,一个是控制台,一个是文件。从控制台显示仅仅是为了方便调试,而在生产环境中的通常做法是落地到日志文件中以便后续分析。Appender一共可以分为以下五种实现:

  • org.apache.log4j.ConsoleAppender(控制台)
  • org.apache.log4j.FileAppender(文件)
  • org.apache.log4j.DailyRollingFileAppender(每天滚动产生一个日志文件)
  • org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候滚动产生一个新文件)
  • org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方,需要Receiver实现)

通常ConsoleAppender较多用于调试,控制台显示日志信息会非常直观。生产环境中,如果数据量不是很大且允许按照天为单位进行滚动切分则推荐使用DailyRollingFileAppender 以便每天产生一个日志文件。如果日志数据量很大,需要按照固定大小进行滚动切分,则推荐使用RollingFileAppender,当日志文件达到预设阈值则会滚动切分,产生一个新的文件。本文提供配置示例和运行结果如下:

log4j.rootLogger=DEBUG,Console,File,DailyRollingFile,RollingFile
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

#File
log4j.appender.File=org.apache.log4j.FileAppender
log4j.appender.File.File=/Users/w3sun/github/log4j/log_file.log
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

#DailyRollingFile
log4j.appender.DailyRollingFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DailyRollingFile.File=/Users/w3sun/github/log4j/log_daily_rolling.log
log4j.appender.DailyRollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.DailyRollingFile.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

#RollingFile
log4j.appender.RollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.RollingFile.File=/Users/w3sun/github/log4j/log_rolling.log
log4j.appender.RollingFile.MaxFileSize=1KB
log4j.appender.RollingFile.MaxBackupIndex=5
log4j.appender.RollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.RollingFile.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

Console控制台和File中在上文中已经演示过,为了演示按照天为单位滚动和大小滚动,需要作出时间上的一些调整,调整完毕后将程序进行小小修改:

@Test
  public void testLogger() {
    for (int i = 0; i < 10000000; i++) {
      logger.trace("---trace level---");
      logger.info("---info level---");
      logger.debug("----debug level---");
      logger.warn("---warn level---");
      logger.error("---error level---");
      logger.fatal("---fatal level---");
    }
  }

对于DailyRollingFileAppender而言,按天滚动分割后文件名将已日期结尾:log_daily_rolling.log.2017-12-01,

而对于RollingFileAppender而言,则会按照当前日志文件大小进行滚动切分且后缀名以数字结尾,如:log_rolling.log.2,

其配置中MaxFileSize定义了日志文件大小的最大值,可以根据实际需求来定 10KB或者 100KB等。MaxBackupIndex则限定了所保存日志文件的最大个数。假如日志文件数量超过该值则会进行覆盖操作以考虑生产环境下硬盘的容量问题。

Log4j Appender通过使用Layout(布局)格式化日志条目。常用的格式化为“一次一行”式日志文件的布局是PatternLayout,其使用一个模式字符串,就像C/C++函数printf那样。此外还有HTMLLayout和XMLLayout,使用HTML或XML格式的时候会更方便。

日志信息的格式(布局)配置

通常使用log4j.appender.appenderName.layout=className配置语法指定logger输出内容及格式,Log4j目前支持如下Layout:

  • org.apache.log4j.HTMLLayout(HTML表格形式布局)
  • org.apache.log4j.PatternLayout(灵活地指定布局模式)
  • org.apache.log4j.SimpleLayout(包含日志信息级别和信息字符串),
  • org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)

TTCC[Time Thread Category Component(时间、线程、类别、组件)]是log4j使用的消息格式,具有完整的模式转换表为:

模式参数 描述
%p 输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%% 输出一个”%”字符
%r 输出自应用程序启动到输出该log信息耗费的毫秒数
%t 输出产生该日志事件的线程名
%l 输出日志事件的发生位置,相当于%c.%M(%F:%L)组合,包括类全名、方法、文件名以及在代码中的行数
%c 输出日志信息所属的类目,通常就是类全名
%M 输出产生日志信息的方法名
%F 输出日志消息产生时所在的文件名
%L 输出代码中的行号
%m 输出代码中指定的具体日志信息
%n 输出一个回车换行符,Windows平台为”rn”,Unix平台为”n”
%x 输出和当前线程相关联的NDC(嵌套诊断环境)
%d 输出日志时间或时间,默认格式为ISO8601,可以指定格式如:%d{yyyy/MM/dd HH:mm:ss,SSS}

PatternLayout很灵活,生产环境下推荐使用,此外可以通过ConversionPattern灵活配置输出属性。

log4j.appender.DailyRollingFile.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

格式化以后的日志格式:

2017-12-02 00:00:00,009 [main] WARN [Log4jTest] - ---warn level---

可以看到%d[/kbd]对应与日志产生时间[kbd]2017-12-02 00:00:00,009%t对应于产生该日志事件的线程名[main]%-5p对应于WARN日志等级所占的字符个数,因为Log4j中字符最多的ERROR等级,因此该值设置为5即可。[%c]与输出日志信息所属的类目即类名[Log4jTest]相对应。%m%n输出代码中指定的具体日志信息并添加换行。

当然,Log4j在将日志信息输出到文件的时候同样可以指定写入过程是追加还是覆盖,该特性通过log4j.appender.appenderName.Append = false|true进行设置,默认为追加模式(true)。

不同级别日志分离输出配置

生产环境下,有时候需要将需要把一些ERROR及以上级别的日志单独存到指定文件,通过属性Threshold可以很方便的实现日志局部输出级别设定,但是logger根配置中的日志级别需要保持最低等级,否则局部级别是不生效的。

如果指定某个appender的Threshold为WARN,那这个appender输出的日志信息就是WARN级别以及WARN以上的级别。实际实用的话rootLogger里配置DEBUG,然后某个文件专门存储ERRO日志,就配置下Threshold为ERROR。

log4j.rootLogger=DEBUG,Console,DFile,EFile
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#DFile
log4j.appender.DFile.Threshold=DEBUG
log4j.appender.DFile=org.apache.log4j.FileAppender
log4j.appender.DFile.File=/Users/w3sun/github/log4j/log_dfile.log
log4j.appender.DFile.layout=org.apache.log4j.PatternLayout
log4j.appender.DFile.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#EFile
log4j.appender.EFile.Threshold=ERROR
log4j.appender.EFile=org.apache.log4j.FileAppender
log4j.appender.EFile.File=/Users/w3sun/github/log4j/log_efile.log
log4j.appender.EFile.layout=org.apache.log4j.PatternLayout
log4j.appender.EFile.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

随后可以看到控制台输出:

2017-12-02 10:38:05,676 [main] INFO [Log4jTest] - ---info level--- 
2017-12-02 10:38:05,676 [main] DEBUG [Log4jTest] - ----debug level--- 
2017-12-02 10:38:05,676 [main] WARN [Log4jTest] - ---warn level--- 
2017-12-02 10:38:05,676 [main] ERROR [Log4jTest] - ---error level--- 
2017-12-02 10:38:05,676 [main] FATAL [Log4jTest] - ---fatal level---

log_dfile.log输出:

2017-12-02 10:37:59,462 [main] INFO  [Log4jTest] - ---info level---
2017-12-02 10:37:59,463 [main] DEBUG [Log4jTest] - ----debug level---
2017-12-02 10:37:59,463 [main] WARN  [Log4jTest] - ---warn level---
2017-12-02 10:37:59,463 [main] ERROR [Log4jTest] - ---error level---
2017-12-02 10:37:59,464 [main] FATAL [Log4jTest] - ---fatal level---

log_efile.log输出:

2017-12-02 10:37:59,463 [main] ERROR [Log4jTest] - ---error level---
2017-12-02 10:37:59,464 [main] FATAL [Log4jTest] - ---fatal level---
2017-12-02 10:37:59,465 [main] ERROR [Log4jTest] - ---error level---
2017-12-02 10:37:59,465 [main] FATAL [Log4jTest] - ---fatal level---
2017-12-02 10:37:59,466 [main] ERROR [Log4jTest] - ---error level---
2017-12-02 10:37:59,467 [main] FATAL [Log4jTest] - ---fatal level---
2017-12-02 10:37:59,469 [main] ERROR [Log4jTest] - ---error level---
2017-12-02 10:37:59,469 [main] FATAL [Log4jTest] - ---fatal level---

至此,基本使用方法介绍完毕。

转载请注明:雪后西塘 » 一篇文章学会使用Log4j

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址