Log4j 2.x 简明配置(一)

本文主要内容:


image.png

1. 概述

我们为了分析程序的执行情况,需要把我们关心的一些调试信息、错误信息等保存到日志中,Log4j就是一个优秀的日志记录框架。本文基于Log4j 2.x版本,简要介绍Log4j 2.x的架构,讲述几个常用的Appender,Layout,Logger的配置方法,最后给出log4j2.xml的最简配置实例。

本文是Log4j的入门文章,不会讲解诸如异步机制、多进程共享、自定义Level、Filter、插件机制等高级特性,通过阅读本文,读者可以初步掌握Log4j 2.x的使用方法。

Log4j 2.x 拥有如下特性[1]

  1. 支持异步机制,基于LMAX Disruptor Libaray(高吞吐量、低延时),比Log4j 1.x快10倍。
  2. 独立的垃圾回收机制,在Web应用中产生的GC压力小,使Web应用有更好的响应性能。
  3. 支持插件机制,具有很好的扩展性,配置文件简单,不需要指定类名。
  4. Appender支持自定义Layout,输出格式可定制。
  5. 使用JDK1.5提供的并发机制,解决Log4j 1.x的死锁问题,降低同步开销。

2. 架构图[2]

Log4j 2.x 类图

我们使用 LogManager 的静态方法LogManager.getLogger("name")获取 Logger 实例时,LogManager 首先分配一个 LoggerContext,由 LoggerContext 来实例化具体的Logger,并给 Logger 绑定一个 LoggerConfig,LoggerConfig的属性由关联的 Configuration 决定,包括 Appenders 和 Filters。

3. Configuration配置

Configuration包含了Log4j的所有配置,可以通过配置文件和编写代码来配置。Log4j在初始化时,会自动加载classpath路径中的配置文件来配置Configuration,Log4j支持4种格式的配置文件:XML,JSON,YAML 和 properties,Log4j根据文件名称按照优先级从高到低进行搜索,直到匹配到一个配置文件为止,顺序如下:

1. 系统属性`log4j.configurationFile`指定的配置文件
2. `log4j2-test.properties`
3. `log4j2-test.yaml` or `log4j2-test.yml`
4. `log4j2-test.json` or `log4j2-test.jsn`
5. `log4j2-test.xml`
6. `log4j2.properties`
7. `log4j2.yaml` or `log4j2.yml`
8. `log4j2.json` or `log4j2.jsn`
9. `log4j2.xml`
10. 以上配置文件都没有找到,或者文件配置格式错误,实例化默认的`DefaultConfiguration`输出日志到`console`

本文只讲解 XML 配置文件的使用方法,其它3种方式请参见官方文档 JSON,YAML,Properties。

3.1 XML配置文件

xml配置文件支持 简明(concise)模式 和 严格(strict)模式,简明模式不能使用XML Schema[3]校验正确性,为了保证log4j2.xml配置的正确性,建议使用严格模式来编写xml配置文件。

XML Schema又称为XML Schema Definition(XSD),基于XML编写,用于校验xml文档语法的正确性。

通过分析Log4j-config.xsd定义的Schema,我们可以得出log4j2.xml配置文件模板:

;

  
  
  
    
    ...
  

  
  
    value
    
    ...
  
  
  
  
    
    
  
  
    
    ...
  
  
  
  
  
  
  
    
    
      
      
        
        value
      
      
      
    
    ...
    
    
      
      
    
  
  
  
    
    
      
      
      
      
    
    ...
    
    
      
    
  

注意,所有节点的定义顺序不能改变,下面简要说明每个节点的作用,之后介绍详细用法。

  • 根节点Configuration对应类图的Configuration类,表示LoggerContext关联的所有配置。
  • [可选] CustomLevel/CustomLevels自定义日志级别。
  • [可选] Properties 自定义变量集合,作用域为整个Configuration,可以被Filter,Appender,Layout等其他节点通过${变量名}引用。
  • [可选] Filter/Filters 分级过滤事件(events),只过滤传递给关联节点的事件,Configuration节点下的Filter过滤所有事件。
  • Appenders 定义日志输出方式和格式,支持控制台、文件、网络等多种输出方式,通过Layout节点指定丰富的输出格式。
  • Loggers 定义所有LoggerConfig配置,一个Logger节点对应一个LoggerConfig,Root节点对应root logger的LoggerConfig,通过AppenderRef节点指定Appender。
3.1.1 Appender

Appender指定了日志的输出地方,Log4j 2.x内置了各种各样的Appender,可以把日志输出到控制台,文件,网络服务器,数据库等等,我们先看看Appender的类继承关系:

Appender类图.jpg

每个Appender都有一个name属性,被LoggerConfig通过AppenderRef引用。通常我们会把日志打印到控制台和文件中,下面我们就来学习如何配置它们。

ConsoleAppender

我们使用ConsoleAppender把日志内容输出到标准控制台,System.out或者System.err,默认输出到System.out,同时ConsoleAppender必须指定一个Layout来格式化输出样式。

表1. ConsoleAppender常用参数表

参数名 类型 必须配置xml 默认值 用途
name String true 名称,Logger通过AppenderRef属性引用
layout Layout false "%m%n" 输出格式化样式
filter Filter false 过滤传递给Appender的LogEvents
ignoreExceptions boolean false true 在LogEvents处理过程中发生的异常是否传递给调用者
target String false "SYSTEM_OUT" 输出目的地,"SYSTEM_OUT"或者"SYSTEM_ERR",二选一

配置实例,Console是ConsoleAppender的插件名称(参考插件机制[4]),我们在xml配置文件中只能配置Appender的插件名,不能直接配置Appender的类名:



  
    
    
      
    
  
  
    
      
    
  

PatternLayout是一个Layout实例,指定格式化输出样式, "%m%n" 相当于 System.out.println("msg") ,后续章节会详细讲解Layout的配置方法。

FileAppender

FileAppender把日志内容输出到fileName指定的文件中。

表2. FileAppender常用参数表

参数名 类型 必须配置xml 默认值 用途
name String true 名称,Logger通过AppenderRef属性引用
fileName String true "" 输出文件的文件名,如果文件不存在,会自动创建
layout Layout false "%m%n" 输出格式化样式
filter Filter false 过滤传递给Appender的LogEvents
ignoreExceptions boolean false true 在LogEvents处理过程中发生的异常是否传递给调用者

配置示例,FileAppender的插件名称是File



  
    
      
        %d %p %c{1.} [%t] %m%n
      
    
  
  
    
      
    
  

fileName指定的文件名,相对路径和绝对路径都可以。

RandomAccessFileAppender

RandomAccessFileAppender和FileAppender功能相同,但是具有更好的性能表现,RandomAccessFileAppender内部使用ByteBuffer + RandomAccessFile,默认bufferSize为256Kb,FileAppender内部使用BufferedOutputStream,默认bufferSize为8Kb。

配置方法和FileAppender一样,只需要把File换成RandomAccessFile,其他属性不变:



  
    
      
        %d %p %c{1.} [%t] %m%n
      
    
  
  
    
      
    
  

☆ RollingFileAppender

FileAppender和RandomAccessFileAppender会把所有日志写入到fileName指定的文件中,随着写入日志越来越多,日志文件会变得越来越大,此时写入操作就会很耗时,导致性能极速下降。为了解决这个问题,我们可以把日志文件按照某种规则拆分成多个小文件,这就是RollingFileAppender的特性。

RollingFileAppender依赖TriggeringPolicyRolloverStrategy这两个机制来实现日志文件拆分归档。TriggeringPolicy作为触发器,决定日志拆分的触发条件;RolloverStrategy决定日志文件的归档策略。

相对于FileAppender,我们看看RollingFileAppender增加的几个参数:

参数名 类型 必须配置xml 默认值 用途
filePattern String true 定义归档日志的文件名
policy TriggeringPolicy true 指定日志拆分归档(rollover)的触发条件
strategy RolloverStrategy false DefaultRolloverStrategy 指定日志归档文件的执行策略
1) TriggeringPolicy

Log4j 2.x已经帮我们实现了几个常用的TriggeringPolicy,基于时间、基于存储空间、在JVM启动时、定时任务调度等触发机制,我们先看TriggeringPolicy的类图,然后依次分析每种Triggering的用法。

TriggeringPolicy类图

TriggeringPolicy按照触发方式可以分为两种:事件触发自动触发

  • 事件触发(TimeBasedTriggeringPolicy,SizeBasedTriggeringPolicy)
    当调用logger的写入日志方法时,LoggerConfig生成LogEvent事件,传递给RollingFileAppender,Appender再把事件传递给RollingFileManager,由RollingFileManager调用isTriggeringEvent方法,如果该方法返回true就触发rollover,返回false则不触发。

  • 自动触发(OnStartupTriggeringPolicy,CronTriggeringPolicy)
    这两个触发器的isTriggeringEvent方法始终返回false,它们在initialize方法中启动自己的调度逻辑,按照自己的规则自动触发rollover。

OnStartupTriggeringPolicy

顾名思义,OnStartupTriggeringPolicy会在每次启动应用程序时触发归档动作。

参数名 类型 必须配置xml 默认值 用途
minSize long false 1 文件大小(字节数)>=minSize时,触发归档操作,如果minSize等于0,强制创建一个空的归档文件。

必须满足下面2个条件:

  1. 日志文件创建时间早于程序启动时间,一般都满足
  2. 日志文件大小大于等于minSize(字节)

以下配置示例,当程序启动时,且文件大小达到1KB时触发归档操作。



  
    
      
        %d %p %c{1.} [%t] %m%n
          
      
      
    
  
  
    
      
    
  

RollinfFile是RollingFileAppender的插件名称,fileName是日志文件名称,filePattern是归档的文件名称策略。

SizeBasedTriggeringPolicy

按照日志文件的大小来触发,当日志文件达到预设的大小时,自动触发归档(rollover)。

参数名 类型 必须配置xml 默认值 用途
size String false 10MB 当前日志文件的最大size,支持单位:KB/MB/GB

size属性的语法,我们分析源代码可以得出3个原则,见代码注释:

public final class FileSize {
    private static final long KB = 1024;
    private static final long MB = KB * KB;
    private static final long GB = KB * MB;

    // 1. 匹配size的正则表达式
    private static final Pattern VALUE_PATTERN =
        Pattern.compile("([0-9]+([\\.,][0-9]+)?)\\s*(|K|M|G)B?", Pattern.CASE_INSENSITIVE);

    public static long parse(final String string, final long defaultValue) {
        final Matcher matcher = VALUE_PATTERN.matcher(string);

        // Valid input?
        if (matcher.matches()) {
            try {
                // 2. size解析成long类型,忽略小数部分
                final long value = NumberFormat.getNumberInstance(Locale.getDefault()).parse(
                    matcher.group(1)).longValue();

                // Get units specified
                final String units = matcher.group(3);

                if (units.isEmpty()) {
                    return value;
                } else if (units.equalsIgnoreCase("K")) { // 3. 单位忽略大小写
                    return value * KB;
                } else if (units.equalsIgnoreCase("M")) {
                    return value * MB;
                } else if (units.equalsIgnoreCase("G")) {
                    return value * GB;
                } else {
                    LOGGER.error("FileSize units not recognized: " + string);
                    return defaultValue;
                }
            } catch (final ParseException e) {
                LOGGER.error("FileSize unable to parse numeric part: " + string, e);
                return defaultValue;
            }
        }
        LOGGER.error("FileSize unable to parse bytes: " + string);
        return defaultValue;
    }
}

以下配置示例,当日志文件大小达到250MB时,触发归档动作。



  
    
      
        %d %p %c{1.} [%t] %m%n
          
      
      
    
  
  
    
      
    
  

size会被解析成long类型,单位不区分大小,空格和B可以省略,以下写法都表示 250MB。

size="250 MB"
size="250.1 MB"
size="250mb"
size="250m"

TimeBasedTriggeringPolicy

按照时间间隔周期性触发归档,上一次归档后,间隔时间达到设定的时间后自动触发归档。

参数名 类型 必须配置xml 默认值 用途
interval int false 1 触发归档的时间间隔,单位由filePattern%d日期格式指定
modulate boolean false false 是否对interval取模,决定了下一次触发的时间点
maxRandomDelay int false 0 单位:秒,下一次触发时间会在interval基础上,增加一个随机的毫秒数Random.nextLong(0, 1+maxRandomDelay*1000)
  • interval 支持SimpleDateFormat[5]格式的大部分符号,按匹配优先级从高到低,见下表:
匹配优先级 格式符 含义
最高 S 毫秒 millis
s second
m minute
H,K,h,k hour
D,d,F,E day
w,W 星期 week
M month
最低 y year

举几个匹配的例子:

%d{yyyy-MM-dd-HH} 匹配单位是
%d{yyyy-MM-dd}匹配单位是
%d{yyyy-MM-dd HHmmss}匹配单位是

我们来看看匹配filePattern的源码,已省略不相关代码:

/**
 * Parses the rollover pattern.
 */
public class PatternProcessor {
    private static final char YEAR_CHAR = 'y';
    private static final char MONTH_CHAR = 'M';
    private static final char[] WEEK_CHARS = {'w', 'W'};
    private static final char[] DAY_CHARS = {'D', 'd', 'F', 'E'};
    private static final char[] HOUR_CHARS = {'H', 'K', 'h', 'k'};
    private static final char MINUTE_CHAR = 'm';
    private static final char SECOND_CHAR = 's';
    private static final char MILLIS_CHAR = 'S';

    private RolloverFrequency frequency = null;
    
    // pattern 就是RollingFileAppender中,我们配置的 filePattern 属性
    public PatternProcessor(final String pattern) {
        this.pattern = pattern;
        ... //预处理filePattern字符串
        for (final ArrayPatternConverter converter : patternConverters) {
            if (converter instanceof DatePatternConverter) {
                final DatePatternConverter dateConverter = (DatePatternConverter) converter;
                // 匹配 interval 的计时单位
                frequency = calculateFrequency(dateConverter.getPattern());
            }
        }
    }
    
    // 基于 interval, modulate 计算下一次归档时间点
    public long getNextTime(final long currentMillis, final int increment, final boolean modulus) {
        prevFileTime = nextFileTime;
        long nextTime;
        
        // 这里说明 filePattern 参数必须指定,且格式正确。
        if (frequency == null) {
            throw new IllegalStateException("Pattern does not contain a date");
        }
        final Calendar currentCal = Calendar.getInstance();
        currentCal.setTimeInMillis(currentMillis);
        final Calendar cal = Calendar.getInstance();
        currentCal.setMinimalDaysInFirstWeek(7);
        cal.setMinimalDaysInFirstWeek(7);
        cal.set(currentCal.get(Calendar.YEAR), 0, 1, 0, 0, 0);
        cal.set(Calendar.MILLISECOND, 0);
       // 根据 frequency 匹配的单位来增加时间间隔 interval
        if (frequency == RolloverFrequency.ANNUALLY) {
            increment(cal, Calendar.YEAR, increment, modulus);
            nextTime = cal.getTimeInMillis();
            cal.add(Calendar.YEAR, -1);
            nextFileTime = cal.getTimeInMillis();
            return debugGetNextTime(nextTime);
        }
        cal.set(Calendar.MONTH, currentCal.get(Calendar.MONTH));
        if (frequency == RolloverFrequency.MONTHLY) {
            increment(cal, Calendar.MONTH, increment, modulus);
            nextTime = cal.getTimeInMillis();
            cal.add(Calendar.MONTH, -1);
            nextFileTime = cal.getTimeInMillis();
            return debugGetNextTime(nextTime);
        }

        ...

        cal.set(Calendar.MILLISECOND, currentCal.get(Calendar.MILLISECOND));
        increment(cal, Calendar.MILLISECOND, increment, modulus);
        nextTime = cal.getTimeInMillis();
        cal.add(Calendar.MILLISECOND, -1);
        nextFileTime = cal.getTimeInMillis();
        return debugGetNextTime(nextTime);
    }

    // 匹配 interval 计时单位,毫秒优先级最高,依次递减到年,如果都没有匹配到,则返回null,会导致Appedner抛date格式不正确的异常。
    private RolloverFrequency calculateFrequency(final String pattern) {
        if (patternContains(pattern, MILLIS_CHAR)) {
            return RolloverFrequency.EVERY_MILLISECOND;
        }
        if (patternContains(pattern, SECOND_CHAR)) {
            return RolloverFrequency.EVERY_SECOND;
        }
        if (patternContains(pattern, MINUTE_CHAR)) {
            return RolloverFrequency.EVERY_MINUTE;
        }
        if (patternContains(pattern, HOUR_CHARS)) {
            return RolloverFrequency.HOURLY;
        }
        if (patternContains(pattern, DAY_CHARS)) {
            return RolloverFrequency.DAILY;
        }
        if (patternContains(pattern, WEEK_CHARS)) {
            return RolloverFrequency.WEEKLY;
        }
        if (patternContains(pattern, MONTH_CHAR)) {
            return RolloverFrequency.MONTHLY;
        }
        if (patternContains(pattern, YEAR_CHAR)) {
            return RolloverFrequency.ANNUALLY;
        }
        return null;
    }
}
  • modulate 以小时举例,当前系统时间是上午3点,interval是4,如果modulate=true,那么上午4点触发下一次归档,如果modulate=false,那么上午7点触发下一次归档,之后每间隔4小时触发一次归档,如下图所示。

以下配置示例,下一次归档时间是4天后,之后每隔4天触发一次归档。



  
    
      
        %d %p %c{1.} [%t] %m%n
          
      
      
    
  
  
    
      
    
  

CronTriggeringPolicy

TimeBasedTriggeringPolicy按照时间间隔来触发,控制力度太单一,为了实现多样化的定时调度,基于cron 表达式实现了CronTriggeringPolicy。

参数名 类型 必须配置xml 默认值 用途
schedule String false "0 0 0 * * ?" CronExpression[6],语法非常灵活,默认值表示:每天0时0分0秒触发归档
evaluateOnStartup boolean false false true,在TriggeringPolicy初始时评估是否需要补充一次归档;false,不检测
  • 为什么需要evaluateOnStartup

当程序因为某些原因重启了,或者log4j2.xml配置文件触发了Reconfiguration,在这段时间内可能存在满足cron表达式的时间点,所以在启动CronTriggeringPolicy时需要做一次评估。
evaluateOnStartup 评估策略由cron表达式来决定,如果在上一次归档时间(日志文件创建时间)和系统当前时间这段时间内,存在满足cron表达式规则的时间点,那么在CronTriggeringPolicy启动时先直接触发一次归档,否则不触发。

以下配置示例,表示每天的0时0分自动触发归档,且不做启动评估。



  
    
      
        %d %p %c{1.} [%t] %m%n
          
      
      
    
  
  
    
      
    
  

CompositeTriggeringPolicy

单一的触发机制有时并不能满足我们的要求,使用CompositeTriggeringPolicy组合多个TriggeringPolicy,其中所有的TriggeringPolicy可以同时触发归档。

以下配置示例,同时支持4种触发机制:1)程序启动时,如果文件大于0触发归档。2)日志文件大于20MB时触发归档。3)每2天触发一次归档。4)每天8点触发一次归档。



  
    
      
        %d %p %c{1.} [%t] %m%n
          
      
        
        
        
        
      
    
  
  
    
      
    
  

2) RolloverStrategy

RolloverStrategy负责执行日志归档(rollover),它定义了多个执行策略,每一个策略定义成Action,最后依次执行这些Action来完成具体的归档操作。

RolloverStrategy类图

从类图可以看出,每个Strategy包括多个Action,这些Action可以分为两类:自动匹配手动配置

  • 自动匹配Action
    包含3个压缩Action,负责压缩日志文件,由filePattern的后缀名决定使用哪种压缩算法。
    FileRenameAction修改日志文件名,由filePattern的date/time、%i计数和Strategy的参数共同决定归档文件名。
  • 手动配置Action
    包括DeleteActionPosixViewAttributeAction,在xml中配置,本文不介绍具体配置语法。

log4j内置两种Strategy:DefaultRolloverStrategyDirectWriteRolloverStrategy,我们来看RollingFileAppenderf创建RolloverStrategy的流程:

RolloverStrategy创建流程
  • filePattern属性

filePattern属性支持如下匹配规则:

  1. date/time模式: 用%d{}指定,如%d{yyyyMMdd}会被替换成20181001。
  2. %i整数: 每次归档依次递增1。
  3. 压缩模式后缀:支持.gz, .zip, .bz2, .deflate, .pack200.xz ,分别匹配对应的压缩算法。
  4. 匹配Lookups:比如Date,支持SimpleDateFormat。

以下配置示例,如果程序启动时间是2018年7月12日1点0时0分,那么归档文件使用gzip算法压缩,保存在logs/2018-07目录下,归档文件依次是:app-2018071203-1.log.gzapp-2018071205-2.log.gzapp-2018071207-2.log.gz ...



  
    
      
        %d %p %c{1.} [%t] %m%n
          
      
    
  
  
    
      
    
  

  • DefaultRolloverStrategy
    DefaultRolloverStrategy归档策略由filePattern属性和以下属性共同决定:
参数名 类型 必须配置xml 默认值 用途
fileIndex String false "nomax" 指定归档文件的起始编号,取值范围:"min","max","nomax"
min int false 1 归档文件的最小编号
max int false 7 归档文件的最大编号。当归档数量达到max时,执行下一个归档时,会删除最先的日志归档。
compressionLevel int false -1 只有zip压缩模式有效。取值范围0-9,0 不压缩,1 压缩速度最快,9 压缩率最高。

fileIndex三种模式的区别:
min 归档文件从小到大编号,最大不超过max
max 归档文件从大到小编号,最小不超过min
nomax 编号从小到大编号,没有上限。

  • DirectWriteRolloverStrategy
    DirectWriteRolloverStrategy归档策略由filePattern属性和以下属性共同决定:
参数名 类型 必须配置xml 默认值 用途
maxFiles int false Integer.MAX_VALUE 指定归档文件的最大数量。如果归档数量超过最大值,那么删除最早的归档文件。注意:如果配置的值<0或者省略,会被设置成Integer.MAX_VALUE,即不限制数量;如果配置的值是01,会被强制设置成7
compressionLevel int false -1 只有zip压缩模式有效。取值范围0-9,0 不压缩,1 压缩速度最快,9 压缩率最高。

DefaultRolloverStrategyDirectWriteRolloverStrategy的流程区别:

  1. DefaultRolloverStrategy指定fileName,日志写入到fileName指定的文件中,触发归档时,根据filePattern计算出归档文件名,然后把fileName文件重命名为归档名,进行压缩,然后创建一个新的fileName文件,之后的日志写入到新创建的fileName文件中。
  2. DirectWriteRolloverStrategy没有fileName,日志文件名由filePattern匹配所得,日志直接写入到filePattern匹配的归档文件中,触发归档时,进行压缩,然后由filePattern重新匹配一个文件名,之后的日志写入到重新匹配的文件中。

以下配置实例,使用DefaultRolloverStrategy归档策略,日志保存到logs/app.log文件中,每天触发一次归档,同时日志文件每次达到250MB触发一次归档,归档文件依次为:logs/2018-07/app-20180717-1.log.gzlogs/2018-07/app-20180718-2.log.gz… ,最多只有20个归档。



  
    
      
        %d %p %c{1.} [%t] %m%n
      
      
        
        
      
      
    
  
  
    
      
    
  

以下配置实例,使用DirectWriteRolloverStrategy归档策略,日志保存到logs/app-20180717-1.log文件中,1天后创建归档logs/app-20180717-1.log.gz,同时创建新日志文件logs/app-20180718-2.log,依次类推,没有归档文件数量限制 。



  
    
      
        %d %p %c{1.} [%t] %m%n
      
      
        
        
      
    
  
  
    
      
    
  

3.1.2 Layout

Layout负责格式化日志的输出方式,Log4j 2.x内置了多种Layout,如:CsvLogEventLayoutPatternLayoutJsonLayoutXmlLayout等等,我们之前的例子使用的就是PatternLayoutAppender的默认layout也是PatternLayout("%m%n"),本文只介绍PatternLayout的基本使用方法。

参数名 类型 必须配置xml 默认值 用途
pattern String false "%m%n" 输出格式化字符串。

PatternLayoutpattern参数指定输出格式,pattern字符串由字面字符串和多个转换说明符(conversion specifiers)组成,
转换说明符的格式为:

%[format]conversion{param}
% 必须,起始符号。
[format] 可选,部分conversion需要,用于指定输出宽度,对齐方式等
conversion 必须,转换符号
param 可选,部分转换符号需要指定参数,如日期格式等
例如:
%d{yyyy-MM-dd HH:mm:ss} 打印当前时间
%-5level 打印日记级别,并且占5个字符宽度
%M 打印方法名称

下面是一个pattern的示例:

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

输出为:

2018.07.17 at 14:40:10 CST INFO com.alibaba.druid.pool.DruidDataSource 669 init - {dataSource-1} inited

这里是详细的pattern说明。

3.1.3 Logger

一个LoggerConfig对应一个Logger实例,我们通过LogManager.getLogger(Class.getName())来获取Logger实例时,LogManager通过name查找响应的LoggerConfig,然后实例化相应的Logger。

我们来看LoggerConfig的几个重要属性:

参数名 类型 必须配置xml 默认值 用途
name String true "" 指定LoggerConfig的名称,匹配同名的Logger。注意,root LoggerConfig不能配置该属性,它有默认值"root",是所有Logger的父Logger。
level String false "ERROR" 日志输出级别
appender-ref 或者 AppenderRef Appender true null 关联的Appender
additivity boolean false true LogEvent的传递性。true LogEvent处理后传递给父Logger。false LogEvent处理后不再向上传递给父Logger。

下面配置示例,定义了名称为com.foo.bar的Logger,日志级别为trace,日志输出到Console控制台,additivity配置为false,通过com.foo.barLogger打印的日志不会再次传递到rootLogger。如果additivity配置成true,那么通过com.foo.barLogger打印的日志会先打印到控制台,然后传递给rootLogger,再一次打印到控制台。



  
    
      
    
  
  
    
      
    
    
      
    
  

3.1.4 log4j2.xml简明配置

下面是log4j2.xml最简配置的一个示例,输出配置log4j的所有过程日志,配置了ConsoleRollingFile2个Appender,都关联到rootLogger,日志级别为info,程序所有的info日志都会输出到控制台和log.log文件中,每32MB创建一个日志归档,日志的输出格式是:时间 级别 线程名 类名#方法名(文件名:行号):消息



    
        
            
        
        
            
            
        
    
    
        
            
            
        
    

输出格式:

2018-07-19 17:31:33,642 INFO [localhost-startStop-1] com.alibaba.druid.pool.DruidDataSource#init(DruidDataSource.java:669): {dataSource-1} inited

后续

接下来有时间,会讲解Filter,java api,以及SLF4J适配等内容。

附录一 Log4j-config.xsd

帮助分析 log4j2.xml 的结构,XSD语法。

参考资料


  1. Log4j2 概述 http://logging.apache.org/log4j/2.x/manual/index.html ↩

  2. Log4j2 架构 http://logging.apache.org/log4j/2.x/manual/architecture.html ↩

  3. XML Schema 教程 http://www.w3school.com.cn/schema/index.asp ↩

  4. 插件机制 http://logging.apache.org/log4j/2.x/manual/plugins.html ↩

  5. 日期格式化 https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html ↩

  6. Cron Expression http://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/util/CronExpression.html ↩

你可能感兴趣的:(Log4j 2.x 简明配置(一))