1. Introduction
1.导言
Log4j 2 is a popular, open-source logging framework written in Java. It was introduced to overcome various architectural flaws of Log4j. It’s thread-safe, fast, and provides various improvements over its predecessor. It’s distributed under the open-source Apache Software License.
Log4j 2 是一个流行的开源日志框架,使用 Java 编写。它的推出克服了 Log4j 在架构上的各种缺陷。它是线程安全的、快速的,并在其前身的基础上进行了各种改进。它根据开源的 Apache 软件许可证发布。
Log4j 2 is the latest and improved version of the classic Log4j framework that reached the end of its life on August 5, 2015. However, Log4j is still widely used in many Java enterprise applications as a logging framework.
Log4j 2 是经典 Log4j 框架的最新改进版本,该框架已于 2015 年 8 月 5 日寿终正寝。不过,Log4j 仍作为日志框架广泛应用于许多 Java 企业应用程序中。
In this tutorial, we’ll learn about Log4j 2, its benefits over Log4j, and how to configure its core components using the log4j2.properties file in Java.
在本教程中,我们将了解 Log4j 2、它与 Log4j 相比的优势,以及如何使用 Java 中的 log4j2.properties 文件配置其核心组件。
2. Maven Setup
2.Maven 设置
We’ll need the log4j-core dependency in our pom.xml to start with:
首先,我们需要在 pom.xml 中加入 log4j-core 依赖关系:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.20.0</version>
</dependency>
We can find the latest version of log4j-core and log4j-api in the Maven Repository.
我们可以在 Maven Repository 中找到 log4j-core 和 log4j-api 的最新版本。
3. Log4j 2 Logger
3.Log4j 2 Logger
Unlike in Log4j, where we use Logger.getLogger() to get a Logger instance with a specific name, in Log4j 2 we use LogManager.getLogger():
在 Log4j 中,我们使用 Logger.getLogger() 获取具有特定名称的 Logger 实例,而在 Log4j 2 中,我们使用 LogManager.getLogger() 获取 Logger 实例:
private static final Logger logger = LogManager.getLogger(Log4j2Example.class);
The LogManager reads the initial configuration parameters from a configuration file or a configuration class. A Logger is associated with LoggerConfig, which is associated with Appenders that actually deliver the log events.
LogManager 会从配置文件或配置类中读取初始配置参数。Logger 与 LoggerConfig 关联,而 LoggerConfig 与实际传送日志事件的 Appender 关联。
If we call LogManager.getLogger() by passing the same (class) name, we’ll always get the reference of the same logger instance.
如果我们通过传递相同的(类)名称来调用 LogManager.getLogger() ,我们将始终获得相同日志记录器实例的引用。
Both Logger and LoggerConfig are named entities. Each Logger references a LoggerConfig, which can reference its parent, thus achieving the same effect.
Logger 和 LoggerConfig 都是命名实体。每个 Logger 都会引用一个 LoggerConfig ,而 LoggerConfig 可以引用其父实体,从而达到相同的效果。
A Logger follows a named hierarchy. This means a LoggerConfig named “com.baeldung” is a parent of the LoggerConfig named “com.baeldung.foo“.
Logger 遵循命名层次结构。这意味着名为”com.baeldung“的 LoggerConfig 是名为”com.baeldung.foo“的 LoggerConfig 的父节点。
4. Log4j 2 Configuration
4.Log4j 2 配置
Unlike Log4j, which supports configuration only through properties and XML formats, we can define the Log4j 2 configurations using JSON, XML, YAML, or properties format. All these formats are functionally equivalent. Therefore, we can easily convert the configuration done in one format to any other.
Log4j 仅通过属性和 XML 格式支持配置,与之不同的是,我们可以使用JSON、XML、YAML 或属性格式来定义 Log4j 2 配置。所有这些格式在功能上都是等价的。因此,我们可以轻松地将以一种格式完成的配置转换为任何其他格式。
Moreover, Logj2 supports automatic configuration, which means it’s capable of configuring itself automatically during initialization.
此外,Logj2 还支持自动配置,这意味着它能够在初始化过程中自动进行配置。
It scans and locates all the ConfigurationFactory plugins at the start and arranges them in weighted order from highest to lowest – the properties file has the highest precedence of the value of 8, followed by YAML, JSON, and XML.
它会在开始时扫描并定位所有 ConfigurationFactory 插件,并按照从高到低的加权顺序排列 – 属性文件的优先级最高,其值为 8,其次是 YAML、JSON 和 XML。
This means if we have logging configurations in the form of both the properties file and the XML file, then the precedence will be given to the properties file.
这意味着,如果我们同时以属性文件和 XML 文件的形式进行日志配置,那么属性文件将优先。
5. The log4j2.properties File
5.log4j2.properties 文件
When Log4j 2 was released, it didn’t have the support for configuration through the properties file. It started supporting the properties file from the release of version 2.4.
Log4j 2 发布时,还不支持通过属性文件进行配置。从 2.4 版开始,它开始支持属性文件。
The default properties configuration file is always log4j2.properties. The Logger gets the reference of this file from the CLASSPATH.
默认的属性配置文件始终是 log4j2.properties。Logger 会从 CLASSPATH 获取该文件的引用。
However, if we need to use a different configuration file name, we can set it using the system property log4j.configurationFile.
但是,如果我们需要使用不同的配置文件名,我们可以使用系统属性 log4j.configurationFile 进行设置。
The system property may refer to a local file system or may contain a URL. Log4j 2 provides a DefaultConfiguration if it cannot locate a configuration file. In this case, we get the logging output redirected to the console and the root logger level set to ERROR.
系统属性可以指向本地文件系统,也可以包含 URL。如果无法找到配置文件,Log4j 2 将提供 DefaultConfiguration 配置。在这种情况下,我们会将日志输出重定向到控制台,并将 root logger 级别设置为 ERROR。
6. Syntax of the log4j2.properties File
6.log4j2.properties 文件的语法
The syntax of the log4j2.properties file isn’t the same as that of log4j.properties. In the log4j.properties file, every configuration starts with ‘log4j‘, while this has been omitted in the log4j2.properties configuration.
log4j2.properties 文件的语法与 log4j.properties 不同。在 log4j.properties 文件中,每个配置都以”log4j“开头,而在 log4j2.properties 配置中则省略了这一点。
Let’s see the syntax of a general log4j2.properties file:
让我们看看一般 log4j2.properties 文件的语法:
# The root logger with appender name
rootLogger = DEBUG, STDOUT
# Assign STDOUT a valid appender & define its layout
appender.console.name = STDOUT
appender.console.type = Console
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %msg%n
Here, STDOUT is the name of the Appender. As discussed earlier, we can attach multiple appenders to a logger to direct logs to different destinations.
这里,STDOUT 是 Appender 的名称。如前所述,我们可以为一个 logger 附加多个 Appender 以将日志导向不同的目的地。
Also, we should define a root logger in every Log4j 2 configuration. Otherwise, a default root LoggerConfig that has an ERROR level and ConsoleAppender is used.
此外,我们应在每个 Log4j 2 配置中定义一个根日志记录器。否则,就会使用具有 ERROR 级别和 ConsoleAppender 的默认 root LoggerConfig。
7. Examples
7.实例
Now, let’s understand the log4j2.properties file configurations for different appenders with the help of some examples.
现在,让我们借助一些示例来了解 不同 appenders 的 log4j2.properties 文件配置。
7.1. Sample Program
7.1.程序样本
Let’s start with an example application that logs some messages:
让我们从一个记录一些信息的应用程序示例开始:
public class Log4j2ConsoleAndFile {
private static final Logger logger = LogManager.getLogger(Log4j2ConsoleAndFile.class);
public static void main(String[] args) {
logger.info("Hello World!");
logger.debug("Hello World!");
}
}
7.2. Console Logging
7.2.控制台日志
The console is the default place for logging messages if no configuration file is located. Let’s create a log4j2.properties configuration for the console Appender with the root logger and also define the logging level for it:
如果没有配置文件,控制台是记录消息的默认位置。让我们使用 root 日志记录器为控制台 Appender 创建 log4j2.properties 配置,并为其定义日志记录级别:
# Root Logger
rootLogger=DEBUG, STDOUT
# Direct log messages to stdout
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
Here, we’ve defined a log4j2.properties file with the following specifications:
在这里,我们定义了一个 log4j2.properties 文件,其规格如下:
- We’ve defined the level of the root logger as DEBUG. This means that we’ll get all the log events with level DEBUG and above. We’ve also defined a name for the appender as STDOUT.
- Since we want to direct the logs to the console, we assigned the Appender type as Console. We should note that the word console in the key name is only a convention and not mandatory.
- Then, we specify the pattern in which we want to print the log messages.
Let’s also understand the meaning of each of the conversion characters in the layout pattern that we’ve used:
让我们来了解一下我们使用的 布局模式中每个转换字符的含义:
- %-5level adds the log-level information to each log statement. It signifies that the priority of the logging event is left-justified to a width of five characters.
- %d adds the timestamp in the defined format.
- %t adds the thread name to the log statement
- %c{1} prints the qualified class name, optionally followed by package names (precision qualifier), that logs the specific log statement.
- %msg prints the actual log message.
- %n adds a new line after every log statement.
Thus, when we run our sample application, we get the following lines printed on the console:
因此,当我们运行示例应用程序时,控制台上会打印出以下几行:
[INFO ] 2023-08-05 23:04:03.255 [main] Log4j2ConsoleAndFile - Hello World!
[DEBUG] 2023-08-05 23:04:03.255 [main] Log4j2ConsoleAndFile - Hello World!
The class PatternLayout explains more about conversion characters that we can use based on our needs.
PatternLayout类解释了有关转换字符的更多信息,我们可以根据需要使用这些字符。
7.3. Multiple Destinations
7.3.多个目的地
As discussed earlier, we can redirect the log events to multiple destinations:
如前所述,我们可以将日志事件重定向到多个目的地:
# Root Logger
rootLogger=INFO, STDOUT, LOGFILE
# Direct log messages to STDOUT
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
# Direct to a file
appender.file.type = File
appender.file.name = LOGFILE
appender.file.fileName = baeldung/logs/log4j2.log
appender.file.layout.type = PatternLayout
appender.file.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
appender.file.filter.threshold.type = ThresholdFilter
appender.file.filter.threshold.level = info
Here, we’ve used two appenders to redirect the log messages to both the file and console. We’ve named them STDOUT and LOGFILE. Additionally, we’ve added both appenders to the root logger.
在这里,我们使用两个 appender 将日志信息重定向到文件和控制台。我们将它们命名为 STDOUT 和 LOGFILE。此外,我们还将这两个 appenders 添加到了 root 日志记录器。
To redirect the log messages to a file, we need to specify the file name with its location.
要将日志信息重定向到文件,我们需要指定文件名及其位置。
We’ve also used ThresholdFilter, which filters out the log messages with a certain log level and above. Finally, we’ve specified the threshold.level as INFO. Thus, all the log messages with level INFO or above will be printed to the file.
我们还使用了 ThresholdFilter, 它可以过滤出具有一定日志级别及以上的日志信息。最后,我们将 threshold.level 指定为 INFO。因此,所有级别为 INFO 或以上的日志信息都将被打印到文件中。
When we run our sample application, we get only the following line printed on the console as well as the log4j2.log file:
当我们运行示例应用程序时,控制台和 log4j2.log 文件中只打印了以下一行:
[INFO ] 2023-08-05 23:04:03.255 [main] Log4j2ConsoleAndFile - Hello World!
8. Conclusion
8.结论
In this article, we explored Log4j 2 and its benefits over Log4j. We’ve also understood the syntax of a log4j2.properties file and some simple examples of configuring a log4j2.properties file.
在本文中,我们探讨了 Log4j 2 及其相对于 Log4j 的优势。我们还了解了 log4j2.properties 文件的语法以及配置 log4j2.properties 文件的一些简单示例。
As always, the examples that accompany the article are available over on GitHub.
与往常一样,本文附带的示例可在 GitHub 上获取。