优雅灵活记录Java日志 By log4j2

log4j是一个被广泛使用的Java日志记录框架,通过使用该框架,我们可以在自己的项目中根据自身需求灵活配置日志输出格式,从而获得期望格式的日志信息,用于后续分析、错误排查等。log4j2则是原有log4j的升级版本,该版本使用更加简洁方便。

log4j2使用步骤

注:小编我目前使用的 IDE 为 Intellij,自从写Android代码时使用了Android Studio后,就爱上了 Intellij 这一系列的产品了。

  1. 下载 log4j2 的JAR包:从http://logging.apache.org/log4j/2.x/download.html 官网下载最新版Apache Log4j 2 binary 压缩包,解压后会得到许多JAR包,只需要将其中的 log4j-core-2.7.jar 和 log4j-api-2.7.jar 添加到项目中即可;
  2. 在项目的 src 文件夹下添加 log4j2.xml 文件,该文件为 log4j2 的配置文件,默认文件内容为:


 
 
 
 
 
 
 
 
 
 

  1. 在项目中使用 log4j2:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class LogTest {
    // 获取 Logger 实例
    static Logger logger = LogManager.getLogger();
    public static void main(String[] args) {

        logger.trace("I am a trace message");
        logger.warn("I am a warn message");
        logger.error("I am a error message");
        logger.info("I am a info message");
        logger.fatal("I am a fatal message");
    }
}

效果如下图所示:

日志效果图-1

咦?上面明明定义了五条日志信息,怎么控制台就显示了两条呢?细致的读者maybe会有如此困惑。小小剧透一波:此玄机存在于 log4j 的配置文件中,若想一探究竟,就继续随我一起仔细探究吧!

log4j2 日志级别

log4j2 中默认的日志级别为:trace < debug < info < warn < error < fatal
当设置了日志输出级别时,当前级别及以上级别的日志会输出,而当前级别以下级别的日志则不会输出,系统默认输出级别为 error,也就是说默认设置下,只有 error 和 fatal这两级日志会输出,这也就解释了为什么上面只输出了两条日志信息

  • trace:即追踪,程序每推进一步均可输出一条trace日志,主要用于展现程序运行轨迹
  • debug:调试
  • info:输出你感兴趣的信息,一般用于基本的、高层次的诊断信息。在长时间运行的代码段开始运行及结束运行时应该产生消息,以便知道现在系统在干什么。但是这样的信息不宜太过频繁
  • warn:提示信息
  • error:错误信息,显示一个错误,或一个通用的错误情况,但还不至于会将系统挂起。这种程度的错误一般会触发邮件的发送,将消息发送到alert list中,运维人员可以在文档中记录这个bug并提交
  • fatal:会导致程序崩溃的重大错误,用在极端的情形中,即必须马上获得注意的情况

log4j2 日志组件

下图是Apache官网贴出的log4j的类图,通过该类图可以清晰地看出log4j的类层次结构。

优雅灵活记录Java日志 By log4j2_第1张图片
log4j2类层次结构图

由类图可以看出:log4j2中主要包含如下概念/组成部分:Loggerontext、Configuration、Filter、Logger、LoggerConfig、Appender、Layout等,后文会详细解释这些概念。

log4j2 由以下三个核心组件组成:

  • Loggers:Logger负责捕捉事件并将其发送给合适的Appender;
  • Appenders:负责对Logger传来的日志事件进行处理,如过滤、格式化等,然后将处理后的日志事件记录到指定位置;
  • Layouts:负责对日志事件中的数据进行转换和格式化;Layouts决定了数据在一条日志记录中的最终形式。

当Logger记录一个事件时,它将事件转发给适当的Appender。然后Appender使用Layout来对日志记录进行格式化,并将其发送给控制台、文件或其它目标位置。另外,Filters可以让你进一步指定一个Appender是否可以应用在一条特定的日志记录上。在日志配置中,Filters并不是必需的,但可以让你更灵活地控制日志消息的流动。

log4j2核心概念

Loggerontext
LoggerContext在Logger系统中扮演着锚点的角色,一般来说,一个应用只会存在于一个LoggerContext中,但是也可以根据使用场景的差异和项目的具体需求,为一个项目配置多个不同的LoggerContext。在同一个LoggerContext下,log系统是可以互通的。

Configuration
Configuration顾名思义,即是当前LoggerContext中的所有Logger的配置环境,每一个LoggerContext均会拥有一个动态可配置的Configuration,该Configuration 包含了当前LoggerContext环境中所有的Loggers、Appenders、Filters、Layouts等配置信息。注意:在reConfiguration期间,新旧Configuration均会同时存在,然而一旦重配过程结束,旧的Configuration就会失效,配置信息会重定向至新的Configuration中。

Logger
Logger是一个通过给LoggerManager.getLogger()方法传递特定的Logger名称而获得的一个AbstractLogger实现类对象,该对象自身并不具体进行任何操作,而是通过关联一个LoggerConfig完成具体的Logger配置,并通过实现AbstractLogger的方法进行具体的操作。注意:通过同一个名称获得的Logger对象会指向同一个Logger引用。

LoggerConfig
LoggerConfig包含了一个Logger对象的具体配置信息,如该Logger关联的Appenders、Filters、过滤级别等。

Filter
过滤器,定义LogEvent的过滤规则。log4j中定义了三种过滤状态:Accept(接受)、Deny(拒绝)和Nertual(中立)。
Accept:该LogEvent将被执行而无需调用其它过滤器;
Deny:忽略当前LogEvent,并将该LogEvent的控制权移交给过滤器调用者;
Nertual:中立,也就是说,当前LogEvent应该传递给其它过滤器,如果没有别的过滤器可以传递了,那么就由现在这个过滤器来处理。

Appender
Appender意为输出目的地,负责将日志消息转发给期望的输出。它负责接收日志事件,使用Layout格式化事件,然后将其发送给对应的目标。对于一个日志事件,我们可以使用多个Appenders来将事件发送到不同的目标位置。例如,我们可以在控制台上显示一个简单的日志事件的同时,将其通过邮件的方式发送给指定的接收者。目前,Appender可以是console、文件、远程socket服务器、Apache Flume、JMS以及远程 UNIX 系统日志守护进程等。

注意:
在某一个Logger中被启用的log请求将被转发到该Logger相关联的的所有Appenders上,并且还会被转发到LoggerConfig的父级的Appenders上。由此可知,如果设置不当的话,会产生一系列的遗传反应。如:Logger A 继承自 Logger B,并且两者均是root的子节点,若LoggerConfig B 中定义了一个文件作为Appender的话,那么使用LoggerConfig A和LoggerConfig B的logger 的log请求都会在该文件中打印,文件中便会显示很多重复的日志信息,这会给日志分析带来不必要的麻烦。还好这是可以被避免的,通过设置 Appender 的 additivity属性为false即可。(默认情况下,additivity="true")

Layout:
Layout用于定义LogEvent的输出格式。

log4j2配置方式

log4j2 有如下四种配置方式,可以根据你的意愿、喜好等自行选择:

  1. 通过配置文件进行配置,配置文件可以是 XML、 JSON、 YAML 和 properties这四种类型中的任意一种;
  2. 在代码中创建 ConfigurationFactory 和 Configuration 累的实现类;
  3. 在代码中调用Configuration 接口的 API 在默认配置类上添加组件;
  4. 在代码中调用内部类 Logger 的方法实现自定义。

通过配置文件配置log4j

目前小编还只使用了文件的配置方式,所以本文着重于通过配置文件配置log4j,以后有机会再好好研究一波代码配置的方式,然后与看官分享 _

文件配置优先级

对应于四类配置文件:XML、 JSON、 YAML 和 properties,Log4j 分别有与之相应的 ConfigurationFactory 实现类,不同的实现类可以加载不同扩展名的配置文件中的配置信息。当 Log4j 启动时会按照一定的优先级顺序在classpath(一般是项目的src文件夹下)查找项目中的配置文件,若找到一个配置文件,就调用与当前文件扩展名对应的ConfigurationFactory实现类加载该配置文件中的配置信息,否则继续查找下一优先级的配置文件,若未找到任何配置文件,就使用默认配置DefaultConfiguration。
不同配置文件的优先级如下图所示:

优雅灵活记录Java日志 By log4j2_第2张图片
配置文件优先级

配置文件详解

如下是个比较完整详细的 XML 形式的配置文件,该文件通过注释的方式提供简要解释以便于理解。




    
    
        %d{yyyy-MM-dd HH:mm:ss z} %-5level %class{36}%L%M - %msg%xEx%n

        ${web:rootDir}/logs
        5M
        debug
    

    
    

        
        
            
            
            
            
            
            

            
            
        

        
        
        
        
            
                
                
            
            
            
            
        

        
        
            
                
                
            
            
            
        

        
        
            
                
            
            
            
        

    

    
    
        
        
            
            
            
            
        
    


log4j2 配置节点分析

configuration

configuration决定了当前上下文的loggers配置信息,是配置文件根节点,主要包含如下属性值:

  • name:当前配置的名称
  • dest:输出位置,标准错误流、文件或远程邮件发送
  • status:是否记录 Log4j 自身的event信息,默认为 off,可选值有: "trace", "debug", "info", "warn", "error" and "fatal"
  • strict:是否使用strict xml形式,configuration支持concise(简约)和strict(严格)两种模式的xml。简约模式下,使得文件编写起来更简洁

Appenders

Appenders用于定义当前LoggerContext中所需要使用到的Appender。目前log4j2提供了多种不同类型的appender可供配置。如下介绍几种常用的,如果想了解更全面的信息,可移步官网

Appender类型

ConsoleAppender:
ConsoleAppender是最常用的Appenders之一,它只是将日志消息显示到控制台上。log4j2的默认Appender即为ConsoleAppender。

ConsoleAppender参数如下:

  • filter:用于决定是否需要使用该Appender来处理当前日志事件,通过使用CompositeFilter可以组合使用多个Filter;
  • layout:用于决定如何对日志记录进行格式化,默认情况下使用“%m%n”,它会在每一行显示一条日志记录;
  • follow:用于决定Appender是否需要了解输出(system.out或者system.err)的变化,默认情况是不需要跟踪这种变化;
  • name:用于设置Appender的名字;
  • ignoreExceptions:默认为true,用于决定是否需要记录在日志事件处理过程中出现的异常;
  • target:用于指定输出目标位置,默认情况下使用SYSTEM_OUT,但也可以修改成SYSTEM_ERR

FileAppender:
FileAppenders将日志记录写入到文件中,它负责打开、关闭文件,向文件中追加日志记录,并对文件进行加锁,以免数据被破坏或者覆盖。
FileAppender参数如下:

  • append:是否追加写入,默认为true,表示将日志事件追加在文件末尾,若设置为false,则每次都会先清空文件,然后将日志事件写入文件中;
  • bufferedIO:默认为true,表示使用缓存,也就是说每次进行日志输出时会先将日志事件输出到缓存中,缓存满或者设置了immediateFlush 时,才将日志事件写入磁盘文件。注意:llocking属性不能与该属性同时使用;
  • bufferSize:缓存大小,默认为8192字节;
  • createOnDemand:当需要时才创建日志文件,即只有当有日志事件需要被输出到该文件中时才创建文件;
  • filter:过滤器,含义与ConsoleAppender中相似;
  • fileName:日志文件名;
  • immediateFlush:表示每次写完日志后均进行flush,这可以保证每次日志均被写入磁盘中了;
  • layout:格式化;
  • locking:是否对该日志文件加锁,一般用于多主机场景中,默认为false,该属性对性能影响较大,需要谨慎使用;
  • name:Appender名称;
  • ignoreExceptions:用法同ConsoleAppender。

RollingFileAppender

滚动输出日志到文件中,RollingFileAppender 根据TriggeringPolicy 和RolloverPolicy滚动将日志事件输出到fileName指定的文件中。TriggeringPolicy用于决定是否触发RolloverPolicy所定义的日志滚动操作,若未设置RolloverPolicy ,则会使用默认设置 DefaultRolloverStrategy。

RollingFileAppender参数如下:

  • append、bufferedIO、bufferSize、createOnDemand、filter、fileName、immediateFlush、layout、name、ignoreExceptions等属性与FileAppender类似,就不一一概述了;
  • filePattern:存档日志文件的文件名模式,模式格式依赖于所采用的RolloverPolicy ;
  • policy:TriggeringPolicy,触发策略;触发策略有如下几种:Composite Triggering Policy(组合策略)、CronTriggeringPolicy(定时触发)、OnStartupTriggeringPolicy(JVM虚拟机启动时触发)、SizeBasedTriggeringPolicy(基于日志文件大小触发)、TimeBasedTriggeringPolicy(基于时间触发)
  • strategy:RolloverStrategy,决定存档文件名称、数量和位置的策略。

其它Appender:
SyslogAppenders将日志记录发送给本地或者远程系统的日志服务;SMTPAppender会将日志内容以邮件的形式发送出去;FailoverAppender设置在处理日志的过程中,如果一个或者多个Appender失败,自动切换到其他Appender上等,更多信息详见官网

Layout

log4j2中使用较多的Layout为PatternLayout,格式为:


%d{HH:mm:ss:SSS}:日志输出时间,精确到毫秒
%t:当前线程名称
%-5level:日志级别,-5表示左对齐并固定输出5个字符,如果不足右边补零
%logger:logger名称
%msg:日志文本
%n:换行
%F:文件所在的类文件名
%L:行号
%M:所在方法名
%l:语句所在的行数,包括类名,方法名,文件名,行数

你可能感兴趣的:(优雅灵活记录Java日志 By log4j2)