对Log4j2的配置可以通过四种方式之一完成:
- 配置文件,支持的格式包括XML、JSON、YAML、Properties
- 编程式配置,创建ConfigurationFactory和Configuration实现类
- 编程式配置,调用Configuration接口暴露的API,对默认实现添加组件
- 编程式配置,调用Logger暴露的接口
自动配置
Log4j2能够在初始化时进行自动配置,它会定位到所有ConfigurationFactory并根据权重值对它们排序。开箱即用的ConfigurationFactory实现有4种,分别处理XML、JSON、YAML、Properties格式的配置文件。具体配置步骤如下
- 检查系统属性log4j.configurationFile,如果该属性存在,会尝试利用ConfigurationFactory加载匹配扩展名的文件
- 如果没有上述属性,尝试加载类路径下的log4j2-test.propertie
- 如果没有上述文件,尝试加载类路径下的log4j2-test.yaml或者log4j2-test.yml
- 如果没有上述文件,尝试加载类路径下的log4j2-test.json或者log4j2-test.jsn
- 如果没有上述文件,尝试加载类路径下的log4j2-test.xml
- 如果没有上述文件,将会按2-5的顺序尝试加载log4j2.*(同样格式后缀的)版本(没有-test后缀)的配置文件
- 如果找不到任何配置文件,使用DefaultConfiguration。此配置直接打印日志到stdout
默认配置
如果没有找到相应的配置文件,则走默认配置,默认配置走的是DefaultConfiguration
类
- 日志级别:ERROR
- 使用Root Logger,使用ConsoleAppender
- 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
- 与appender,logger和properties 元素处于同一层级。 这些filter可以在事件传递到LoggerConfig之前接受或拒绝事件。
- 在logger中。 这些filter可以接受或拒绝特定logger的事件。
- 在appender中。 这些filter可以阻止或产生事件由appender处理。
- 在引用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 Lang的StrSubstitutor和StrLookup类的变体。 以类似于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可以具体翻阅官方文档