掘金 后端 ( ) • 2024-04-09 09:51

theme: smartblue

Configuration

将日志输出插入到应用程序代码需要相当多的计划和努力。 观察显示,大约4%的代码专用于日志记录。 因此,甚至中等大小的应用程序将在其代码中嵌入数千个日志记录语句。 鉴于它们的数量,必须管理这些日志语句而无需手动修改它们。

Log4j 2的配置可以通过以下四种方式之一完成:

  1. 通过以XML,JSON,YAML或properties格式编写的配置文件。
  2. 以编程方式,通过创建ConfigurationFactory和Configuration实现。
  3. 以编程方式,通过调用Configuration接口中暴露的API将组件添加到默认配置。
  4. 以编程方式,通过调用内部Logger类上的方法。

该章节主要侧重于通过配置文件配置Log4j。 有关以编程方式配置Log4j的信息,请参阅Extending Log4j 2和Programmatic Log4j configuration章节。
请注意,与Log4j 1.x不同,Log4j 2 API不暴露任何添加,修改或删除appender和filters或以任何方式操作配置文件的方法。

自动配置

Log4j能够在初始化期间自动配置自身。 当Log4j启动时,它将找到所有ConfigurationFactory插件,并按照从最高到最低的权重顺序排列它们。 Log4j包含四个ConfigurationFactory实现:一个用于JSON,一个用于YAML,一个用properties,一个用于XML。

  1. Log4j将检查“log4j.configurationFile”系统属性,如果设置,将尝试使用与文件扩展名匹配的ConfigurationFactory加载配置。
  2. 如果未设置系统属性,则properties 的ConfigurationFactory将在类路径中查找log4j2-test.properties。
  3. 如果没有找到这样的文件,YAML的ConfigurationFactory将在类路径中查找log4j2-test.yaml或log4j2-test.yml
  4. 如果没有找到这样的文件,JSON的ConfigurationFactory将在类路径中查找log4j2-test.json或log4j2-test.jsn
  5. 如果没有找到这样的文件,XML ConfigurationFactory将在类路径中查找log4j2-test.xml。
  6. 如果找不到test文件,ConfigurationFactory属性将在类路径上查找log4j2.properties。
  7. 如果找不到properties文件,YAML ConfigurationFactory将查找
    类路径上的log4j2.yaml或log4j2.yml。
  8. 如果找不到YAML文件,JSON ConfigurationFactory将在类路径上查找log4j2.json或log4j2.jsn
  9. 如果找不到JSON文件,XML ConfigurationFactory将尝试在类路径上找到log4j2.xml。
  10. 如果找不到配置文件,则将使用DefaultConfiguration。 这将
    导致日志输出转到控制台。

使用myapp的示例应用程序来说明log4j如何完成这一操作。

import com.foo.Bar;
 
// Import log4j classes.
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
 
public class MyApp {
 
    // Define a static logger variable so that it references the
    // Logger instance named "MyApp".
    private static final Logger logger = LogManager.getLogger(MyApp.class);
 
    public static void main(final String... args) {
 
        // Set up a simple configuration that logs on the console.
 
        logger.trace("Entering application.");
        Bar bar = new Bar();
        if (!bar.doIt()) {
            logger.error("Didn't do it.");
        }
        logger.trace("Exiting application.");
    }
}

MyApp首先导入log4j相关类。然后,它定义了一个名为MyApp的静态Logger变量,该变量恰好是类的完全限定名。

MyApp使用包com.foo中定义的bar类。

package com.foo;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
 
public class Bar {
  static final Logger logger = LogManager.getLogger(Bar.class.getName());
 
  public boolean doIt() {
    logger.entry();
    logger.error("Did it again!");
    return logger.exit(false);
  }
}

如果无法找到配置文件,log4j将提供默认配置。在默认配置类中提供的默认配置将设置:

  • PatternLayout绑定到ConsoleAppender,并设置模式“%d {HH:mm:ss.SSS} [%t]%-5level%logger {36} - %msg%n”

请注意,默认情况下,Log4j日志级别是Level.ERROR。

MyApp的输出类似于:

17:13:01.540 [main] ERROR com.foo.Bar - Did it again!
17:13:01.540 [main] ERROR MyApp - Didn't do it.

如前所述,Log4j将首先尝试从配置文件中配置自身。 默认的配置如下所示:

<?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>

将上面的文件作为log4j2.xml放入类路径后,您将获得与上面列出的结果相同的结果。 将根级别更改为trace将导致结果类似于:

17:13:01.540 [main] TRACE MyApp - Entering application.
17:13:01.540 [main] TRACE com.foo.Bar - entry
17:13:01.540 [main] ERROR com.foo.Bar - Did it again!
17:13:01.540 [main] TRACE com.foo.Bar - exit with (false)
17:13:01.540 [main] ERROR MyApp - Didn't do it.
17:13:01.540 [main] TRACE MyApp - Exiting application.

可加性

也许你希望从com.foo.Bar之外的所有内容中删除所有TRACE输出。 简单地更改日志级别将无法完成任务。 相反,解决方案是在配置中添加新的Logger定义:

<Logger name="com.foo.Bar" level="TRACE"/>
<Root level="ERROR">
<AppenderRef ref="STDOUT">
</Root>

使用此配置,将记录来自com.foo.Bar的所有日志事件,同时仅记录来自所有其他组件的错误事件。

在前面的示例中,com.foo.Bar中的所有事件仍写入控制台。 这是因为com.foo.Bar的记录器没有配置任何appender,而其父进程已配置。 实际上,是以下配置

<?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>
    <Logger name="com.foo.Bar" level="trace">
      <AppenderRef ref="Console"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

将输出一下日志

17:13:01.540 [main] TRACE com.foo.Bar - entry
17:13:01.540 [main] TRACE com.foo.Bar - entry
17:13:01.540 [main] ERROR com.foo.Bar - Did it again!
17:13:01.540 [main] TRACE com.foo.Bar - exit (false)
17:13:01.540 [main] TRACE com.foo.Bar - exit (false)
17:13:01.540 [main] ERROR MyApp - Didn't do it.

请注意,来自com.foo.Bar的Trace消息会出现两次。 这是因为首先使用与logger com.foo.Bar关联的appender,它将第一个实例写入Console。 接下来,引用com.foo.Bar的父级,在本例中是root录器。 然后将事件传递给它的appender,它也会写入Console,从而产生第二个实例。 这被称为可加性。 虽然可加性可以是一个非常方便的功能(如前面的第一个示例,其中不需要配置appender引用),但在许多情况下,此行为被认为是不合需要的,因此可以通过将记录器上的additivity属性设置false来禁用它:

<?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>
    <Logger name="com.foo.Bar" level="trace" additivity="false">
      <AppenderRef ref="Console"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

一旦事件到Logger且其可加性设置为false,该事件将不会传递给任何其父记Logger,无论其可加性如何设置。

自动重新配置

从文件加载配置时,Log4j能够自动检测配置文件的更改并重新加载配置。 如果在配置元素上指定了monitorInterval属性并将其设置为非零值,则下次评估和/或记录日志事件时将检查该文件,并且自上次检查后已经过了monitorInterval。 下面的示例显示了如何配置属性,以便仅在至少30秒后检查配置文件的更改。最小配置间隔为5秒。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
...
</Configuration>

配置语法

从版本2.9开始,出于安全原因,Log4j不处理XML文件中的DTD。 如果要将配置拆分为多个文件,请使用XIncludeComposite Configuration

正如前面的示例以及后面的示例所示,Log4j允许您轻松地重新定义日志记录行为,而无需修改应用程序。 可以禁用应用程序某些部分的日志记录,仅在满足特定条件时记录,例如为特定用户执行的操作,将输出路由到Flume或日志报告系统等。能够执行上述操作需要了解配置文件的语法。

XML文件中的configuration元素接受以下几个属性:

属性名 描述 advertiser (可选)广告商插件名称,用于通告单个FileAppender或SocketAppender配置。 唯一提供的广告商插件是'multicastdns' dest “err”,它将输出发送到stderr,或文件路径或URL。 monitorInterval 检查文件配置更改之前必须经过的最短时间(以秒为单位)。 name 配置的名称 packages 以逗号分隔的包名称列表,用于搜索插件。 每个类加载器只加载一次插件,因此更改此值可能对重新配置没有任何影响 scheme 标识类加载器的位置,以定位用于验证配置的XML架构。 仅在strict设置为true时有效。 如果未设置,则不会进行架构验证 shutdownHook 指定在JVM关闭时Log4j是否应自动关闭。 默认情况下启用关闭,但可以通过将此属性设置为“disable”来禁用 shutdownTimeout 指定JVM关闭时,多少毫秒关闭appender和后台任务。 默认值为零,表示每个appender使用其默认超时时间,并且不等待后台任务。 并非所有的appender都会尊重这一点,这是一个提示,并不是绝对保证关闭程序不会花费更长时间。 将此设置得太低会增加丢失尚未写入最终目标的未完成日志事件的风险。 请参阅LoggerContext.stop(long,java.util.concurrent.TimeUnit)。 (如果没有使用shutdownHook设置为“disable”。) status 应记录到控制台的内部Log4j事件的级别。 此属性的有效值为“trace”,“debug”,“info”,“warn”,“error”和“fatal”。 Log4j会将有关初始化,rollover和其他内部操作的详细信息记录到状态记录器。 如果您需要对log4j进行故障排除,可以设置status =“trace”或者,设置系统属性log4j2.debug也会将内部Log4j2日志记录打印到控制台,包括在找到配置文件之前发生的内部日志记录。) strict 允许使用严格的XML格式。 JSON配置不支持 verbose 加载插件时启用诊断信息

可以使用两种XML风格配置Log4j简洁和严谨。 简洁的格式使配置非常简单,因为元素名称与它们所代表的组件相匹配,但它不能用XML验证。 例如,通过在其父appenders元素下声明名为Console的XML元素来配置ConsoleAppender。 但是,元素和属性名称不区分大小写。 此外,可以将属性指定为XML属性,也可以指定为没有属性且具有文本值的XML元素。 所以

<PatternLayout pattern="%m%n"/>

<PatternLayout>
<Pattern>%m%n</Pattern>
</PatternLayout>

是相同的。

下面的文件表示XML配置的结构,但请注意,下面的斜体元素表示将在其位置显示的简明元素名称。

<?xml version="1.0" encoding="UTF-8"?>;
<Configuration>
  <Properties>
    <Property name="name1">value</property>
    <Property name="name2" value="value2"/>
  </Properties>
  <filter  ... />
  <Appenders>
    <appender ... >
      <filter  ... />
    </appender>
    ...
  </Appenders>
  <Loggers>
    <Logger name="name1">
      <filter  ... />
    </Logger>
    ...
    <Root level="level">
      <AppenderRef ref="name"/>
    </Root>
  </Loggers>
</Configuration>

有关示例appender、filter 和logger声明,请参阅本本节示例。

严格XML

除了上面简洁的XML格式之外,Log4j还允许以更“正常”的XML方式指定配置,可以使用XML Schema进行验证。 这是通过将上面的友好元素名称替换为其对象类型来实现的,如下所示。 例如,而不是使用名为Console的元素配置ConsoleAppender而是将其配置为具有包含“Console”的type属性的appender元素。

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

以下是使用严格格式的示例配置。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" strict="true" name="XMLConfigTest"
               packages="org.apache.logging.log4j.test">
  <Properties>
    <Property name="filename">target/test.log</Property>
  </Properties>
  <Filter type="ThresholdFilter" level="trace"/>
 
  <Appenders>
    <Appender type="Console" name="STDOUT">
      <Layout type="PatternLayout" pattern="%m MDC%X%n"/>
      <Filters>
        <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">
      <Layout type="PatternLayout" pattern="%C{1}.%M %m %ex%n"/><!-- class and line number -->
      <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>
    <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
      <Filter type="ThreadContextMapFilter">
        <KeyValuePair key="test" value="123"/>
      </Filter>
      <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>

使用JSON配置

除了XML之外,还可以使用JSON配置Log4j。 JSON格式与简洁的XML格式非常相似。 每个键代表插件的名称,与之关联的键/值对是其属性。 如果一个键包含的不仅仅是一个简单的值,那么它本身就是一个从属插件。 在下面的示例中,ThresholdFilter,Console和PatternLayout都是插件,而Console插件的名称属性将被赋予STDOUT值,并且ThresholdFilter将被分配一个debug级别。

{ "configuration": { "status": "error", "name": "RoutingTest",
                     "packages": "org.apache.logging.log4j.test",
      "properties": {
        "property": { "name": "filename",
                      "value" : "target/rolling1/rollingtest-$${sd:type}.log" }
      },
    "ThresholdFilter": { "level": "debug" },
    "appenders": {
      "Console": { "name": "STDOUT",
        "PatternLayout": { "pattern": "%m%n" },
        "ThresholdFilter": { "level": "debug" }
      },
      "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"},
                "SizeBasedTriggeringPolicy": { "size": "500" }
              }
            },
            { "AppenderRef": "STDOUT", "key": "Audit"}
          ]
        }
      }
    },
    "loggers": {
      "logger": { "name": "EventLogger", "level": "info", "additivity": "false",
                  "AppenderRef": { "ref": "Routing" }},
      "root": { "level": "error", "AppenderRef": { "ref": "STDOUT" }}
    }
  }
}

请注意,在RoutingAppender中,Route元素已声明为数组。 这是有效的,因为每个数组元素都是Route组件。 这对于诸如appender和filters之类的元素不起作用,其中每个元素在简明格式中具有不同的名称。 如果每个appender或filters声明一个名为 appender的“type”的属性,则可以将appenders和filter定义为数组元素。 以下示例说明了这一点以及如何将多个logger声明为数组.

{ "configuration": { "status": "debug", "name": "RoutingTest",
                      "packages": "org.apache.logging.log4j.test",
      "properties": {
        "property": { "name": "filename",
                      "value" : "target/rolling1/rollingtest-$${sd:type}.log" }
      },
    "ThresholdFilter": { "level": "debug" },
    "appenders": {
      "appender": [
         { "type": "Console", "name": "STDOUT", "PatternLayout": { "pattern": "%m%n" }, "ThresholdFilter": { "level": "debug" }},
         { "type": "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"},
                  "SizeBasedTriggeringPolicy": { "size": "500" }
                }
              },
              { "AppenderRef": "STDOUT", "key": "Audit"}
            ]
          }
        }
      ]
    },
    "loggers": {
      "logger": [
        { "name": "EventLogger", "level": "info", "additivity": "false",
          "AppenderRef": { "ref": "Routing" }},
        { "name": "com.foo.bar", "level": "error", "additivity": "false",
          "AppenderRef": { "ref": "STDOUT" }}
      ],
      "root": { "level": "error", "AppenderRef": { "ref": "STDOUT" }}
    }
  }
}

使用JSON配置文件需要额外的运行时依赖性

使用YAML配置

Log4j还支持使用YAML配置文件。 该结构XML和YAML有相同的模式。 例如

Configuration:
  status: warn
  name: YAMLConfigTest
  properties:
    property:
      name: filename
      value: target/test-yaml.log
  thresholdFilter:
    level: debug
  appenders:
    Console:
      name: STDOUT
      PatternLayout:
        Pattern: "%m%n"
    File:
      name: File
      fileName: ${filename}
      PatternLayout:
        Pattern: "%d %p %C{1.} [%t] %m%n"
      Filters:
        ThresholdFilter:
          level: error
 
  Loggers:
    logger:
      -
        name: org.apache.logging.log4j.test1
        level: debug
        additivity: false
        ThreadContextMapFilter:
          KeyValuePair:
            key: test
            value: 123
        AppenderRef:
          ref: STDOUT
      -
        name: org.apache.logging.log4j.test2
        level: debug
        additivity: false
        AppenderRef:
          ref: File
    Root:
      level: error
      AppenderRef:
        ref: STDOUT

使用YAML配置文件需要额外的运行时依赖。

使用Properties配置

从版本2.4开始,Log4j现在支持通过properties文件进行配置。 请注意,属性语法与 Log4j 1.中使用的语法不同。但与XML和JSON配置类似,properties配置根据插件和插件的属性定义配置。

在2.6版本之前,properties配置要求在具有这些名称的属性中以逗号分隔的列表列出appenders、 filters和logger的标识符。然后,些组件中的每一个都以组件开头的属性集定义。标识符不必匹配正在定义的组件的名称,但必须唯一地标识所有属性和子组件, 是组件的一部分。如果标识符列表不存在,则标识符必须不包含'.'。每个组件必须有一个指定的“type”属性来标识组件的插件类型。

从版本2.6开始,不再需要此标识符列表,因为在首次使用时会推断出名称,但是如果您希望使用更复杂的标识,则必须仍然使用该列表。 如果列表存在,将使用它。

与基本组件不同,在创建子组件时,您无法指定包含标识符列表的元素。 相反,您必须使用其类型定义包装器元素,如下面的RollingFileappender中的策略定义中所示。 然后定义该包装元素下面的每个子组件,下面定义了TimeBasedTriggeringPolicy和SizeBasedTriggeringPolicy。

properties配置文件支持advertiser,monitorInterval,name,packages,shutdownHook,shutdownTimeout,status,verbose和dest 属性。 有关这些属性的定义,请参阅Configuration语法

status = error
dest = err
name = PropertiesConfig
 
property.filename = target/rolling/rollingtest.log
 
filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
 
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %m%n
appender.console.filter.threshold.type = ThresholdFilter
appender.console.filter.threshold.level = error
 
appender.rolling.type = RollingFile
appender.rolling.name = RollingFile
appender.rolling.fileName = ${filename}
appender.rolling.filePattern = target/rolling2/test1-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 2
appender.rolling.policies.time.modulate = true
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling.policies.size.size=100MB
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.max = 5
 
logger.rolling.name = com.example.my.app
logger.rolling.level = debug
logger.rolling.additivity = false
logger.rolling.appenderRef.rolling.ref = RollingFile
 
rootLogger.level = info
rootLogger.appenderRef.stdout.ref = STDOUT

配置Loggers

在尝试配置Log4j之前,了解Log4j如何在Log4j中工作至关重要。 如果需要更多信息,请参考Log4j架构章节。 试图在不理解这些概念的情况下配置Log4j可能不会成功。使用logger元素配置LoggerConfig。 logger元素必须具有指定的name属性,通常会指定level属性,并且还可以指定additivity属性。 可以使用TRACE,DEBUG,INFO,WARN,ERROR,ALL或OFF之一日志级别。 如果未指定日志级别,则默认为ERROR。 可以为additivity属性分配值true或false。 如果省略该属性,则将使用默认值true。
LoggerConfig(包括root LoggerConfig)可以配置properties,这些properties将添加到从ThreadContextMap复制的属性中。 可以从Appenders,Filters,Layouts等引用这些properties,就像它们是ThreadContext Map的一部分一样。 这些properties可以包含将在解析配置时解析的变量,也可以包含在记录每个事件时动态解析的变量。 有关使用变量的更多信息,请参见属性替换章节
LoggerConfig还可以配置一个或多个AppenderRef元素。 引用的每个appender将与指定的LoggerConfig关联。 如果在LoggerConfig上配置有多个appender,在处理日志记录事件时,每个都会被调用。
如果未配置,则将使用默认根LoggerConfig,其级别为ERROR且绑定了一个Console appender。 根记录器和其他记录器之间的主要区别是

  1. 根记录器没有name属性。
  2. 根记录器不支持additivity属性,因为它没有父级

配置Appender

使用特定的appender插件的名称或appender元素以及包含appender插件名称的type属性配置appender。 此外,每个appender必须具有一个name属性,该属性的值在appender集中是唯一的。如上一节中所述,loggers将使用该名称来引用appender。
大多数appender还支持layout(可以使用特定的Layout插件的名称作为元素或使用“layout”作为元素名称以及包含layout插件名称的type属性来指定布局。各种appender将包含其正常运行所需的其他属性或元素。

配置过滤器

Log4j允许在4个位置指定过滤器:

  1. 与appender,loggers和properties元素处于同一级别。 这些过滤器可以在将事件传递给LoggerConfig之前接受或拒绝事件。
  2. 在Logger元素中。 这些过滤器可以接受或拒绝特定Logger的事件。
  3. 在一个appender元素。 这些过滤器可以防止或导致事件由appender处理。
  4. 在appender引用元素中。 这些过滤器用于确定Logger是否应将事件路由到appender。

虽然只能配置一个过滤器元素,但该元素可能是filters元素它代表CompositeFilter。 filters元素允许在其中配置任意数量的过滤元素。 以下示例显示如何在ConsoleAppender上配置多个filter。

<?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>
  <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"/>
      <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">
      <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">
        <ThreadContextMapFilter>
          <KeyValuePair key="test" value="123"/>
        </ThreadContextMapFilter>
      </AppenderRef>
      <AppenderRef ref="STDOUT" level="error"/>
    </Logger>
 
    <Root level="trace">
      <AppenderRef ref="STDOUT"/>
    </Root>
  </Loggers>
 
</Configuration>

属性替换

Log4j 2支持在配置中指定标记,引用其他地方定义的属性。 解释配置文件时将解析其中一些属性,而其他属性可能会在运行才解析。为了实现这一功能,Log4j使用了Apache Commons Lang的StrSubstitutor和StrLookup类的变体。这个与Ant或Maven中的方式相似。这允许使用配置本身中声明的属性来解析声明为$ {name}的变量。例如,以下示例RollingFile的fileName在property中被声明。

<?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>

虽然这很有用,但是属性可以来自更多的地方。 为了适应这种情况,Log4j还支持语法$ {prefix:name},其中前缀标识告诉Log4j该变量应在特定上下文中声明。 更多的详细信息,请参阅“Lookups”手册页。 Logj4内置的上下文是:

前缀 上下文 bundle 资源包。格式${bundle:BundleName:BundleKey}.bundle遵循package约定,例如${bundle:com.domain.Messages:MyKey}. ctx 线程上下文映射(MDC) date 使用指定的格式插入当前日期或时间 env 系统环境变量。 格式是${env:ENV_NAME} 和 ${env:ENV_NAME:default_value}. jndi 在默认JNDI上下文中设置的值 jvmrunargs 通过JMX访问的JVM输入参数,但不是主参数; 请参阅RuntimeMXBean.getInputArguments()。 在Android上不可用。 log4j Log4j配置属性。 表达方式$ {log4j:configLocation}和$ {log4j:configParentLocation}分别提供log4j配置文件及其父文件夹的绝对路径。 main 使用MapLookup.setMainArguments(String[])设置的值 map MapMessage中的值 sd StructuredDataMessage中的值。 键“id”将返回的StructuredDataId的名称。 键“type”将返回消息类型。 其他键将从Map中检索单个元素。 sys 系统属性。 格式是$ {sys:some.property}和$ {sys:some.property:default_value}

默认属性

可以在任何Loggers,Filters,Appender等之后和之前直接放置Properties元素,并且在Properties中声明默认属性映射。如果无法在指定的lookup 中找到该值,则将使用默认属性映射中的值。 默认映射预先填充了“hostName”的值,该值是当前系统的主机名或IP地址,“contextName”是当前日志记录上下文的值。 有关示例,请参阅本节中使用的Properties元素。

具有多个前导’$’字符的Lookup变量

StrLookup处理的一个有趣特性是,当每次解析变量时,使用多个前导’$’字符声明 量引用时,只需删除前导’$’。 在前面的示 中,“Routes”元素能够在运行时解析变量。 为此,前缀值被指定为带有两个前导’$’字符的变量。为此,前缀值被指定为带有两个前导’$’字符的变量。 首次处理配置文件时,只删除第一个’$’字符。 因此,当在运行时解析Routes元素时,变量声明“$ {sd:type}”,将导致StructuredDataMessage检查事件,如果存在,则将其type属性的值用作路由键。 并非所有元素都支持在运行时解析变量。

如果未找到与前缀关联的Lookup中的键的值,则将使用与配置文件中的属性声明中的键关联的值。 如果未找到任何值,则将返回变量声明作为值。 可以通过执行以下操作在配置中声明默认值:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
  <Properties>
    <Property name="type">Audit</property>
  </Properties>
  ...
</Configuration>

值得指出的是,处理配置时也不会解析RollingFile appender声明中的变量。 这只是因为整个RollingFile元素的解析被推迟到匹配到值时。 有关更多信息,请参阅RoutingAppender

脚本

Log4j支持在某些组件中使用JSR 223脚本语言。 可以使用任何为JSR 223脚本引擎提供支持的语言。 可以在Scripting Engine网站上找到它们的语言和绑定列表。 但是,其中列出的一些语言(如JavaScript,Groovy和Beanshell)直接支持JSR 223脚本框架,并且只需要引入该语言的jar包。

支持使用脚本的组件,通过在这些组件上配置