log4j2介绍及配置

一、log4j2概述

  在日常的开发,测试和生产环境中,日志记录了应用,服务运行过程中的关键信息,以及出现异常时的堆栈,这些信息常常作为查询,定位,解决问题的关键,因此在任何系统中,对日志的使用得当,将极大的提高程序问题解决的效率。

  Log4j的1.x版本虽然已经被广泛使用于很多应用程序中,但由于出现内存泄漏等bug,代码难以维护,以及需要使用老版本的jdk等劣势,在2015年8月已经玩完。它的替代品,SLF4J,Logback,Log4j2对日志框架做了很多必要的改进。

  SLF4J:SLF4J是众多日志系统的内核,提供统一的接口,不提供具体实现,不是具体可使用可配置的日志系统。

  Logback:提供了对SLF4J具体实现的日志系统,相比Log4j1.x,Logback的性能,使用场景,内存使用等方面的优化要远远强于Log4j1.x。

  Log4j2:Log4j2虽然在各个方面都与logback非常相似,但是却提供了更强的性能和并发性,下一代异步logger,易于拓展自定义需求的架构,是目前使用十分广泛的日志框架。

二、log4j2配置节点说明

  如下图为log4j2的设计架构图,接下里对设计图中涉及的各节点做简单的介绍

  (1)LoggerContext:日志系统上下文

  (2)Configuration:每一个 LoggerContext 都有一个有效的 Configuration, Configuration 包含所有的Appender 、Filter、LoggerConfig ,StrSubstitutor引用和对Layout的格式设置

  (3)Logger : Logger继承自 AbstractLogger,当配置被修改后,它将与不同的 LoggerConfig 相关联,这导致其行为也被改变。

  (4)LoggerConfig:LoggerConfig 对象在 Logger 被声明时创建,它包含了一组用于处理事件的Appender引用,以及一组用于过滤传递给Appender事件的Filter,相当于是Appender的集合。

  (5)Appender:Log4j2 还允许将记录请求输出到多个目标中,而这种输出目标被称为Appender。目前Appender的类型有控制台、文件、socket、Apache Flume、JMS、远程UNIX 系统日志守护进程以及各种数据库API,用户可以根据需要选择将日志输出到不同的目标上,同时在一个Logger的配置中,允许开启多个Appender。

  (6)Filter :Log4j2 提供了Filter 来过滤消息事件,它可被应用于事件传递给LoggerConfig之前,及传递给LoggerConfig之后,即LoggerConfig的前后置拦截器。Filter包含了三种行为: Accept, Deny 或 Neutral,其中Accept,Deny分别代表着接受和拒绝,即过滤器接受或拒绝某种日志过滤表达式等,经过这两种行为处理后将不再经过其他过滤器。Neutral代表着中立,意味着事件应由其他Filter来处理。如果未配置任何Filter,那么事件将直接被处理。

  (7)Layout:Log4j2除了可以输出到不同的目标Appender之外,还支持在目标中定义自定义的日志格式,Layout 负责对日志事件进行格式化,通过配置PatternLayout来实现。

  (8)StrSubstitutor和StrLookup:这两个组件用来对Log4j2中的各项配置进行动态变量赋值。

  (9)日志级别:LoggerConfig会被分配一个日志级别,常用的级别包含TRACE, DEBUG, INFO, WARN, ERROR 和 FATAL

  log4j2介绍及配置

 

三、log4j2简单默认配置

  (1)对Log4j2配置的使用首先需要引入对应的core和api包,需要注意的是,如果项目中只引入了jar包而没有对应的log4j2.xml配置文件,那么在eclipse中运行时则会打印如ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console的异常信息,并且输出logger时可以看到只有error和fatal级别的被输出来,是因为没有配置文件就使用默认的,默认级别是error,所以只有error和fatal输出来。

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.11.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.11.0</version>
</dependency>

  (2)配置简单的log4j2.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>

<!-- 配置LoggerConfig,即Appenders的日志级别为WARN -->
<Configuration status="WARN">  

    <!-- Appenders支持配置多个Appender,支持向不同的目标输送日志,本例为配置向控制台输出 -->
    <Appenders>  
        <Console name="Console" target="SYSTEM_OUT">  
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />  
        </Console>  
    </Appenders>  

    <!-- Loggers支持配置多个Logger,可引用不同的目标Appender,也可根据业务需求定制特定要求的Appender -->
    <Loggers>  
        <Root level="info">  
            <AppenderRef ref="Console" />  
        </Root>  
    </Loggers>  
</Configuration>

  (3)加载配置文件的方式,Java代码手动加载以及Web工程web.xml配置监听及加载

<!-- Web工程方式加载 -->
<
context-param> <param-name>log4jConfiguration</param-name> <param-value>classpath:log4j2.xml</param-value> </context-param> <listener> <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class> </listener>
/**
 * Java代码手动加载配置文件
 */
public class App 
{
    public static void main( String[] args )
    {
        try{
            File file = new File("src/main/resources/log4j2.xml");  
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));  
            final ConfigurationSource source = new ConfigurationSource(in);  
            Configurator.initialize(null, source);  

            Logger logger = LogManager.getLogger(); 
            logger.info("logger init and record...");
            
            logger.error("error log level...");
            logger.warn("warn log level...");
            logger.info("info log level...");
            logger.debug("debug log level...");
            logger.trace("trace log level...");
            
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

  (4)验证结果,区分日志级别

  上面第(3)步的代码执行后打印的结果如下,可见打印了所有级别的日志,却并没有所有都输出到控制台上是因为只会输出比LoggerConfig定义较大的级别日志,级别排序:

TRACE < DEBUG < INFO < WARN < ERROR < FATAL,由于配置文件中LoggerConfig定义的级别为WARN,所以正常只有WARN,ERROR和FATAL会打印,但验证结果多了个INFO,是因为在Logger中引用了控制台的Appender,并单独指定了级别为INFO。

log4j2介绍及配置