log4j2 Configuration(未完待续)

2019-03-23  本文已影响0人  怖呆

简介

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

几种配置方法

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

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

自动配置

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

  1. Log4j将检查log4j.configurationFile系统属性,如果设置,将尝试使用与文件扩展名匹配的ConfigurationFactory加载配置。
  2. 如果未设置系统属性,则ConfigurationFactory属性将在类路径中查找log4j2-test.properties
  3. 如果没有找到这样的文件,YAML ConfigurationFactory将在类路径中查找log4j2-test.yamllog4j2-test.yml
  4. 如果没有找到这样的文件,JSON ConfigurationFactory将在类路径中查找log4j2-test.jsonlog4j2-test.jsn
  5. 如果没有找到这样的文件,XML ConfigurationFactory将在类路径中查找log4j2-test.xml
  6. 如果找不到测试文件,ConfigurationFactory属性将在类路径上查找log4j2.properties
  7. 如果找不到属性文件,YAML ConfigurationFactory将在类路径上查找log4j2.yamllog4j2.yml
  8. 如果找不到YAML文件,JSON ConfigurationFactory将在类路径上查找log4j2.jsonlog4j2.jsn
  9. 如果找不到JSON文件,XML ConfigurationFactory将尝试在类路径上找到log4j2.xml
  10. 如果找不到配置文件,则将使用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类中提供的默认配置将设置:

请注意,默认情况下,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>
上一篇下一篇

猜你喜欢

热点阅读