对Log4j2的配置可以通过四种方式之一完成:

  1. 配置文件,支持的格式包括XML、JSON、YAML、Properties
  2. 编程式配置,创建ConfigurationFactory和Configuration实现类
  3. 编程式配置,调用Configuration接口暴露的API,对默认实现添加组件
  4. 编程式配置,调用Logger暴露的接口

自动配置

Log4j2能够在初始化时进行自动配置,它会定位到所有ConfigurationFactory并根据权重值对它们排序。开箱即用的ConfigurationFactory实现有4种,分别处理XML、JSON、YAML、Properties格式的配置文件。具体配置步骤如下

  1. 检查系统属性log4j.configurationFile,如果该属性存在,会尝试利用ConfigurationFactory加载匹配扩展名的文件
  2. 如果没有上述属性,尝试加载类路径下的log4j2-test.propertie
  3. 如果没有上述文件,尝试加载类路径下的log4j2-test.yaml或者log4j2-test.yml
  4. 如果没有上述文件,尝试加载类路径下的log4j2-test.json或者log4j2-test.jsn
  5. 如果没有上述文件,尝试加载类路径下的log4j2-test.xml
  6. 如果没有上述文件,将会按2-5的顺序尝试加载log4j2.*(同样格式后缀的)版本(没有-test后缀)的配置文件
  7. 如果找不到任何配置文件,使用DefaultConfiguration。此配置直接打印日志到stdout

默认配置

如果没有找到相应的配置文件,则走默认配置,默认配置走的是DefaultConfiguration

  1. 日志级别:ERROR
  2. 使用Root Logger,使用ConsoleAppender
  3. ConsoleAppender日志打印pattern为%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n

如果转成XML表示:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

Additivity

如果你翻阅了前面关于Logback的介绍的话,你可能对这个属性有了一定的了解,我们知道日志的打印会遍历Logger的所有父级,然后调用appender打印日志,场景类似:logback为什么日志会打印两次

配置文件语法

配置格式框架

<?xml version="1.0" encoding="UTF-8"?>;
<Configuration>
  <Properties>
    <Property name="name1">value</property>
    <Property name="name2" value="value2"/>
  </Properties>
  <Filter type="type" level="debug"... />
  <Appenders>
    <Appender type="type" name="name">
      <Filter type="type" marker="FLOW"... />
    </Appender>
    ...
  </Appenders>
  <Loggers>
    <Logger name="name1">
      <Filter type="type" ... />
    </Logger>
    ...
    <Root level="level">
      <AppenderRef ref="name"/>
    </Root>
  </Loggers>
</Configuration>

以下配置语法都只会选择常见的介绍,更加详细的见官方的文档

configuration 标签

monitorInterval

检查配置文件变更的间隔,单位秒,如果发现变更则重新加载配置

name

配置的名称

packages

用逗号分隔的软件包名称列表,用于从哪些包里搜索插件。 每个类加载器仅加载一次插件,因此更改此值可能对重新配置没有任何影响。

status

Log4j内部事件需要打印到控制台的级别。此属性的有效值为“ trace”,“ debug”,“ info”,“ warn”,“ error”和“ fatal”。

strict

启用严格XML格式的使用。 JSON配置中不支持。

verbose

加载插件时启用诊断信息。

<?xml version="1.0" encoding="UTF-8"?>
<!--
    status Log4j2内部事件的日志级别
    strict 是否使用严格XML格式
    name 配置的名称
    packages 此哪些包中加载插件,逗号分隔多个包
    monitorInterval  检查配置文件变更的间隔,单位秒,如果发现变更则重新加载配置
-->
<Configuration status="debug" strict="true" name="XMLConfigTest" monitorInterval="10" packages="org.apache.logging.log4j.test">
    <!-- 定义属性,属性可以在后续使用${} 引用 -->
    <!--
        Log4j2支持很多预定义的上下文属性对象。可以通过 ${prefix:name} 语法引用
        bundle:资源束对象,用法示例 ${bundle:BundleName:BundleKey}
        ctx:线程上下文映射(Thread Context Map,MDC)
        date:当前时间或者日期
        env:系统环境变量
        jndi:JNDI上下文
        jvmrunargs:JVM参数
        sys:系统属性
    -->
    <Properties>
        <Property name="filename">target/test.log</Property>
    </Properties>
    <!--
        过滤器可以出现在四种地方:
        1、全局级别,可以在日志事件传递给日志记录器(LoggerConfig)之前接受/拒绝它
        2、logger元素内部,针对单个日志记录器
        3、appender元素内部,针对单个Appender
        4、AppenderRef元素内部,针对日志记录器+Appender的组合
    -->
    <!-- 全局过滤器 -->
    <Filter type="ThresholdFilter" level="trace"/>
 
    <!-- Appender负责向外输出日志内容 -->
    <Appenders>
        <!-- 基于控制台输出 -->
        <Appender type="Console" name="STDOUT">
            <!-- 日志输出格式 -->
            <Layout type="PatternLayout" pattern="%m MDC%X%n"/>
            <!-- 针对Appender的过滤器 -->
            <Filters>
                <!-- 如果日志事件使用标记FLOW,则拒绝输出日志 -->
                <Filter type="MarkerFilter" marker="FLOW" onMatch="DENY" onMismatch="NEUTRAL"/>
                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="DENY" onMismatch="ACCEPT"/>
            </Filters>
        </Appender>
        <Appender type="Console" name="FLOW">
            <!--
                日志格式(布局),支持的布局:
                CSV布局,包括子类CsvParameterLayout、CsvLogEventLayout
                GELF布局,将JSON压缩为GZIP/ZLIB格式
                HTML布局,生成HTML页面
                JSON布局,生成一系列JSON字符串
                Pattern布局,自定义格式对LogEvent进行格式化
                RFC5424布局
                Syslog布局,格式化为BSD Syslog记录
                XML布局
                YAML布局
            -->
            <Layout type="PatternLayout" pattern="%C{1}.%M %m %ex%n"/>
            <Filters>
                <Filter type="MarkerFilter" marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
                <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
        </Appender>
        <!-- 基于文件输出 -->
        <Appender type="File" name="File" fileName="${filename}">
            <Layout type="PatternLayout">
                <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
            </Layout>
        </Appender>
    </Appenders>
    <!-- 日志记录器 -->
    <Loggers>
        <!--
            level 此日志记录器最低输出级别,大小写不敏感
                  支持TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF。默认ERROR
            additivity:false表示日志事件被此记录器处理过后,不会传递给父记录器再次处理
        -->
        <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
            <!-- 针对日志记录器的过滤器 -->
            <Filter type="ThreadContextMapFilter">
                <KeyValuePair key="test" value="123"/>
            </Filter>
            <!-- 日志记录器关联哪个Appender -->
            <AppenderRef ref="STDOUT"/>
        </Logger>
 
        <Logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
            <AppenderRef ref="File"/>
        </Logger>
        <!-- 根记录器,每个配置都必须有一个根记录器 -->
        <Root level="trace">
            <AppenderRef ref="STDOUT"/>
        </Root>
    </Loggers>
 
</Configuration>

配置Logger

我们配置Logger标签,其实就是在配置LoggerConfig 。Logger标签有name,level,additivity三个属性,首先name必须是唯一的,level就是日志等级,我们之前提到过的诸如TRACE, DEBUG, INFO等此类,如果没有配置,默认是ERROR。additivity默认是true。

LoggerConfig 也可以配置一个或者多个AppenderRef 标签。引用的每个AppenderRef 都将与指定的LoggerConfig关联。 如果在LoggerConfig上配置了多个AppenderRef ,则在处理记录事件时将分别调用每个追加程序。

注:每一个配置文件都必须有一个root logger,如果没有则走默认配置,见上文

配置Appender

可以使用特定的appender插件名称来配置appender,或者使用appender元素和包含appender插件名称的type属性来配置appender。 此外,每个appender都必须具有一个name属性,该属性指定的值在一组附加程序中是唯一的。 Logger将使用该名称来引用上一节中所述的附加程序。

大多数追加程序还支持要配置Layout(可以使用特定的Layout插件的名称作为元素名,也可以使用“ layout”作为元素名称以及包含布局插件的名称的type属性来指定。各种appender将包含它们正常运行所需的其他属性或元素。

配置Filter

Log4j允许在以下四个位置中指定一个filter

  1. 与appender,logger和properties 元素处于同一层级。 这些filter可以在事件传递到LoggerConfig之前接受或拒绝事件。
  2. 在logger中。 这些filter可以接受或拒绝特定logger的事件。
  3. 在appender中。 这些filter可以阻止或产生事件由appender处理。
  4. 在引用appender的中(即AppenderRef)。 这些过滤器用于确定Logger是否应将事件路由到appender。

尽管只能配置一个filter元素【这里并不是指整个配置只能配置一个,指的是一如上的四个位置的每一个位置】,但该元素可以是代表CompositeFilter的filters元素。 filters元素允许在其中配置任意数量的过滤器元素。 以下示例显示如何在ConsoleAppender上配置多个过滤器。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" name="XMLConfigTest" packages="org.apache.logging.log4j.test">
  <Properties>
    <Property name="filename">target/test.log</Property>
  </Properties>
   <!-- 1 -->
  <ThresholdFilter level="trace"/>
 
  <Appenders>
    <Console name="STDOUT">
      <PatternLayout pattern="%m MDC%X%n"/>
    </Console>
    <Console name="FLOW">
      <!-- this pattern outputs class name and line number -->
      <PatternLayout pattern="%C{1}.%M %m %ex%n"/>
      <!-- 2 -->
      <filters>
        <MarkerFilter marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
        <MarkerFilter marker="EXCEPTION" onMatch="ACCEPT" onMismatch="DENY"/>
      </filters>
    </Console>
    <File name="File" fileName="${filename}">
      <PatternLayout>
        <pattern>%d %p %C{1.} [%t] %m%n</pattern>
      </PatternLayout>
    </File>
  </Appenders>
 
  <Loggers>
    <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
    <!-- 3 -->
      <ThreadContextMapFilter>
        <KeyValuePair key="test" value="123"/>
      </ThreadContextMapFilter>
      <AppenderRef ref="STDOUT"/>
    </Logger>
 
    <Logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
      <Property name="user">${sys:user.name}</Property>
      <AppenderRef ref="File">
      <!-- 4 -->
        <ThreadContextMapFilter>
          <KeyValuePair key="test" value="123"/>
        </ThreadContextMapFilter>
      </AppenderRef>
      <AppenderRef ref="STDOUT" level="error"/>
    </Logger>
 
    <Root level="trace">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>
 
</Configuration>

Property 替换

Log4j 2支持在配置中指定标记以引用其他位置定义的属性的功能。 当解释配置文件时,其中一些属性将被解析,而其他属性可能会传递到组件,在运行时将对其进行评估。 为此,Log4j使用了Apache Commons LangStrSubstitutorStrLookup类的变体。 以类似于Ant或Maven的方式,用$ {name}标记需要替换的变量。 例如,以下示例显示了 rolling file appender的文件名被声明为属性。

Log4j还支持语法$ {prefix:name},其中前缀标识告诉Log4j变量名称应在特定上下文中求值。 有关更多详细信息,请参见 Lookups 查阅手册页,或者在后续的文章中查阅。在log4j中也有内置一部分带前缀的上下文,参见官方文档

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" name="RoutingTest" packages="org.apache.logging.log4j.test">
  <Properties>
    <Property name="filename">target/rolling1/rollingtest-$${sd:type}.log</Property>
  </Properties>
  <ThresholdFilter level="debug"/>
 
  <Appenders>
    <Console name="STDOUT">
      <PatternLayout pattern="%m%n"/>
      <ThresholdFilter level="debug"/>
    </Console>
    <Routing name="Routing">
      <Routes pattern="$${sd:type}">
        <Route>
          <RollingFile name="Rolling-${sd:type}" fileName="${filename}"
                       filePattern="target/rolling1/test1-${sd:type}.%i.log.gz">
            <PatternLayout>
              <pattern>%d %p %c{1.} [%t] %m%n</pattern>
            </PatternLayout>
            <SizeBasedTriggeringPolicy size="500" />
          </RollingFile>
        </Route>
        <Route ref="STDOUT" key="Audit"/>
      </Routes>
    </Routing>
  </Appenders>
 
  <Loggers>
    <Logger name="EventLogger" level="info" additivity="false">
      <AppenderRef ref="Routing"/>
    </Logger>
 
    <Root level="error">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>
 
</Configuration>

默认Properties

我们可以使用Properties元素来声明default property ,该元素需放在Configuration元素之后以及声明任何Logger,Filters,Appenders等之前。 如果无法在指定的lookup中找到该值,则将使用default property中的值。 default property预先填充了“ hostName”的值,该值是当前系统的主机名或IP地址,而“ contextName”的值是当前日志记录上下文的值。

其他

还有一些诸如Scripts、Status Messages、System Properties可以具体翻阅官方文档