简介
将日志请求插入应用程序代码需要相当多的计划和努力。
观察显示,大约4%的代码专用于日志记录。
因此,即使是中等规模的应用程序也会在其代码中嵌入数千个日志记录语句。
鉴于它们的数量,必须管理这些日志语句而无需手动修改它们。
几种配置方法
Log4j 2的配置可以通过以下四种方式之一完成:
- 通过以XML,JSON,YAML或Properties 格式编写的配置文件。
- 以编程方式,通过创建
ConfigurationFactory
和Configuration
实现。 - 以编程方式,通过调用
Configuration
接口中公开的API将组件添加到默认配置。 - 以编程方式,通过调用内部Logger类上的方法。
自动配置
Log4j能够在初始化期间自动配置自身。
当Log4j启动时,它将找到所有ConfigurationFactory插件,并按照从最高到最低的加权顺序排列它们。
交付时,Log4j包含四个ConfigurationFactory实现:一个用于JSON,一个用于YAML,一个用于Properties,一个用于XML。
- Log4j将检查
log4j.configurationFile
系统属性,如果设置,将尝试使用与文件扩展名匹配的ConfigurationFactory
加载配置。 - 如果未设置系统属性,则
ConfigurationFactory
属性将在类路径中查找log4j2-test.properties
。 - 如果没有找到这样的文件,YAML ConfigurationFactory将在类路径中查找
log4j2-test.yaml
或log4j2-test.yml
。 - 如果没有找到这样的文件,JSON ConfigurationFactory将在类路径中查找
log4j2-test.json
或log4j2-test.jsn
。 - 如果没有找到这样的文件,XML ConfigurationFactory将在类路径中查找
log4j2-test.xml
。 - 如果找不到测试文件,ConfigurationFactory属性将在类路径上查找
log4j2.properties
。 - 如果找不到属性文件,YAML ConfigurationFactory将在类路径上查找
log4j2.yaml
或log4j2.yml
。 - 如果找不到YAML文件,JSON ConfigurationFactory将在类路径上查找
log4j2.json
或log4j2.jsn
。 - 如果找不到JSON文件,XML ConfigurationFactory将尝试在类路径上找到
log4j2.xml
。 - 如果找不到配置文件,则将使用
DefaultConfiguration
。这将导致日志记录输出转到控制台。
配置例子
下面用简单的两个类,演示基本的配置。
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.");
}
}
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);
}
}
运行MyApp
输出内容:
10:49:51.671 [main] ERROR priv.yanyang.example.log4j2.Bar - Did it again!
10:49:51.676 [main] ERROR priv.yanyang.example.log4j2.MyApp - Didn't do it.
当无法找到配置文件,Log4j将提供默认配置。DefaultConfiguration类中提供的默认配置将设置:
-
ConsoleAppender
附属到root logger。 - 设置
ConsoleAppender
的PatternLayout
为%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n
。
请注意,默认情况下,Log4j会将根记录器分配给Level.ERROR
。
以下是默认的配置选项:
<?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放入类路径后,您将获得与上面列出的结果相同的结果。
将Root
标签的 level
属性 调整为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
级别的日志。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
...
<Logger name="com.foo.Bar"
level="TRACE"/>
<Root level="ERROR">
<AppenderRef ref="Console">
</Root>
...
</Configuration>
使用此配置,将记录来自com.foo.Bar
的所有日志事件,同时仅记录来自所有其他组件的错误事件。
运行结果:
12:12:08.798 [main] TRACE priv.yanyang.example.log4j2.Bar - Enter
12:12:08.801 [main] ERROR priv.yanyang.example.log4j2.Bar - Did it again!
12:12:08.801 [main] TRACE priv.yanyang.example.log4j2.Bar - Exit with(false)
12:12:08.801 [main] ERROR priv.yanyang.example.log4j2.MyApp - Didn't do it.
Additivity
当使用如下配置:
<?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>
然后运行MyApp
,执行结果如下:
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
日志被执行了两次。
这是因为com.foo.Bar
类的日志等级符合Root
(根记录器) 和 com.foo.Bar
两个记录器(logger)。
如果不希望这种情况发生,可以在com.foo.Bar
记录器添加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>
网友评论