1. Overview
1.概述
Logback is one of the most widely used logging frameworks in the Java Community. It’s a replacement for its predecessor, Log4j. Logback offers a faster implementation, provides more options for configuration, and more flexibility in archiving old log files.
Logback是Java社区中使用最广泛的日志框架之一。它是其前身Log4j的替代品。Logback提供了更快的实现方式,提供了更多的配置选项,并在归档旧的日志文件方面具有更大的灵活性。
In this tutorial, we’ll introduce Logback’s architecture and examine how we can use it to make our applications better.
在本教程中,我们将介绍Logback的架构,并研究如何使用它来使我们的应用程序变得更好。
2. Logback Architecture
2.Logback架构
The Logback architecture is comprised of three classes: Logger, Appender, and Layout.
Logback架构由三个类组成。Logger, Appender, 和Layout。
A Logger is a context for log messages. This is the class that applications interact with to create log messages.
Logger是日志消息的一个上下文。这是应用程序与之互动以创建日志信息的类。
Appenders place log messages in their final destinations. A Logger can have more than one Appender. We generally think of Appenders as being attached to text files, but Logback is much more potent than that.
Appender将日志信息放置在其最终目的地。一个Logger可以有一个以上的Appender。我们通常认为Appenders是附在文本文件上的,但Logback比这更有效力。
Layout prepares messages for outputting. Logback supports the creation of custom classes for formatting messages, as well as robust configuration options for the existing ones.
Layout为输出的消息做准备。Logback支持创建用于格式化消息的自定义类,以及现有类的强大配置选项。
3. Setup
3.设置
3.1. Maven Dependency
3.1.Maven的依赖性
Logback uses the Simple Logging Facade for Java (SLF4J) as its native interface. Before we can start logging messages, we need to add Logback and SLF4J to our pom.xml:
Logback使用Simple Logging Facade for Java(SLF4J)作为其本地接口。在我们开始记录消息之前,我们需要将Logback和SLF4J加入我们的pom.xml。
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
<scope>test</scope>
</dependency>
Maven Central has the latest version of the Logback Core and the most recent version of slf4j-api.
Maven Central有最新版本的Logback Core和最新版本的slf4j-api。
3.2. Classpath
3.2.类路径
Logback also requires logback-classic.jar on the classpath for runtime.
Logback还需要logback-classic.jar在classpath上运行。
We’ll add this to pom.xml as a test dependency:
我们将把它添加到pom.xml中,作为一个测试依赖。
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>
4. Basic Example and Configuration
4.基本例子和配置
Let’s start with a quick example of using Logback in an application.
让我们从一个在应用程序中使用Logback的快速例子开始。
First, we need a configuration file. We’ll create a text file named logback.xml and put it somewhere in our classpath:
首先,我们需要一个配置文件。我们将创建一个名为logback.xml的文本文件,并将其放在classpath的某个地方。
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Next, we need a simple class with a main method:
接下来,我们需要一个带有main方法的简单类。
public class Example {
private static final Logger logger
= LoggerFactory.getLogger(Example.class);
public static void main(String[] args) {
logger.info("Example log from {}", Example.class.getSimpleName());
}
}
This class creates a Logger and calls info() to generate a log message.
这个类创建了一个Logger并调用info()来生成一个日志信息。
When we run Example, we see our message logged to the console:
当我们运行Example,时,我们看到我们的信息被记录到控制台。
20:34:22.136 [main] INFO Example - Example log from Example
It’s easy to see why Logback is so popular; we’re up and running in minutes.
不难看出为什么Logback如此受欢迎;我们在几分钟内就能启动和运行。
This configuration and code give us a few hints as to how this works:
这个配置和代码给了我们一些提示,告诉我们这是如何工作的。
- We have an appender named STDOUT that references class name ConsoleAppender.
- There is a pattern that describes the format of our log message.
- Our code creates a Logger and we passed our message to it via an info() method.
Now that we understand the basics, let’s have a closer look.
现在我们了解了基本情况,让我们仔细看看。
5. Logger Contexts
5.Logger Contexts
5.1. Creating a Context
5.1.创建一个背景
To log a message to Logback, we initialize a Logger from SLF4J or Logback:
为了向Logback记录消息,我们从SLF4J或Logback初始化一个Logger。
private static final Logger logger
= LoggerFactory.getLogger(Example.class);
Then we use it:
然后我们使用它。
logger.info("Example log from {}", Example.class.getSimpleName());
This is our logging context. When we created it, we passed LoggerFactory our class. This gives the Logger a name (there is also an overload that accepts a String).
这就是我们的日志上下文。当我们创建它时,我们传递了LoggerFactory我们的类。这给了Logger一个名字(也有一个接受字符串的重载)。
Logging contexts exist in a hierarchy that closely resembles the Java object hierarchy:
日志上下文存在于一个与Java对象层次结构非常相似的层次结构中。
- A logger is an ancestor when its name, followed by a dot, prefixes a descendant logger‘s name
- A logger is a parent when there are no ancestors between it and a child
For example, the Example class below is in the com.baeldung.logback package. There’s another class named ExampleAppender in the com.baeldung.logback.appenders package.
例如,下面的Example类是在com.baeldung.logback包中。在com.baeldung.logback.appenders包中还有一个名为ExampleAppender的类。
ExampleAppender’s Logger is a child of Example’s Logger.
ExampleAppender的记录器是Example的记录器的子女。
All loggers are descendants of the predefined root logger.
所有记录器都是预定义根记录器的后代。
A Logger has a Level, which can be set either via configuration or with Logger.setLevel(). Setting the level in code overrides configuration files.
一个Logger有一个Level,可以通过配置或Logger.setLevel()来设置。在代码中设置级别会覆盖配置文件。
The possible levels are, in order of precedence: TRACE, DEBUG, INFO, WARN and ERROR. Each level has a corresponding method that we use to log a message at that level.
可能的级别依次是。TRACE、DEBUG、INFO、WARN和ERROR。每个级别都有一个相应的方法,我们用来记录该级别的消息。
If a Logger isn’t explicitly assigned a level, it inherits the level of its closest ancestor. The root logger defaults to DEBUG. We’ll see how to override this below.
如果一个日志记录器没有明确指定一个级别,它将继承其最接近的祖先的级别。根日志记录器默认为DEBUG。我们将在下面看到如何覆盖这个。
5.2. Using a Context
5.2.使用语境
Let’s create an example program that demonstrates using a context within logging hierarchies:
让我们创建一个示例程序,演示在日志层次结构中使用上下文。
ch.qos.logback.classic.Logger parentLogger =
(ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.logback");
parentLogger.setLevel(Level.INFO);
Logger childlogger =
(ch.qos.logback.classic.Logger)LoggerFactory.getLogger("com.baeldung.logback.tests");
parentLogger.warn("This message is logged because WARN > INFO.");
parentLogger.debug("This message is not logged because DEBUG < INFO.");
childlogger.info("INFO == INFO");
childlogger.debug("DEBUG < INFO");
When we run this, we see these messages:
当我们运行这个时,我们看到这些信息。
20:31:29.586 [main] WARN com.baeldung.logback - This message is logged because WARN > INFO.
20:31:29.594 [main] INFO com.baeldung.logback.tests - INFO == INFO
We start by retrieving a Logger named com.baeldung.logback and cast it to a ch.qos.logback.classic.Logger.
我们首先检索一个名为Logger的com.baeldung.logback,并将其投给ch.qos.logback.classic.Logger.。
A Logback context is needed to set the level in the next statement; note that the SLF4J’s abstract logger does not implement setLevel().
在下一条语句中,需要一个Logback上下文来设置级别;注意,SLF4J的抽象logger并没有实现setLevel()。
We set the level of our context to INFO. Then we create another logger named com.baeldung.logback.tests.
我们将上下文的级别设置为INFO。然后我们创建另一个日志记录器,名为com.baeldung.logback.test.。
Finally, we log two messages with each context to demonstrate the hierarchy. Logback logs the WARN and INFO messages, and filters the DEBUG messages.
最后,我们在每个上下文中记录两条消息,以展示层次结构。Logback记录WARN和INFO消息,并过滤DEBUG消息。
Now let’s use the root logger:
现在让我们使用根记录器。
ch.qos.logback.classic.Logger logger =
(ch.qos.logback.classic.Logger)LoggerFactory.getLogger("com.baeldung.logback");
logger.debug("Hi there!");
Logger rootLogger =
(ch.qos.logback.classic.Logger)LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
logger.debug("This message is logged because DEBUG == DEBUG.");
rootLogger.setLevel(Level.ERROR);
logger.warn("This message is not logged because WARN < ERROR.");
logger.error("This is logged.");
We see these messages when we execute this snippet:
当我们执行这个片段时,我们看到这些信息。
20:44:44.241 [main] DEBUG com.baeldung.logback - Hi there!
20:44:44.243 [main] DEBUG com.baeldung.logback - This message is logged because DEBUG == DEBUG.
20:44:44.243 [main] ERROR com.baeldung.logback - This is logged.
To summarize, we started with a Logger context and printed a DEBUG message.
总结一下,我们从一个Logger上下文开始,打印了一个DEBUG消息。
Then we retrieved the root logger using its statically defined name, and set its level to ERROR.
然后我们使用静态定义的名称检索根记录器,并将其级别设置为ERROR.。
Finally, we demonstrated that Logback does actually filter any statement less than an error.
最后,我们证明了Logback确实可以过滤任何小于错误的语句。
5.3. Parameterized Messages
5.3.参数化消息
Unlike the messages in the sample snippets above, most useful log messages require appending Strings. This entails allocating memory, serializing objects, concatenating Strings, and potentially cleaning up the garbage later.
与上述示例片段中的消息不同,大多数有用的日志消息需要追加字符串。这需要分配内存、序列化对象、连接字符串,并可能在之后清理垃圾。
Consider the following message:
请考虑以下信息。
log.debug("Current count is " + count);
We incur the cost of building the message whether the Logger logs the message or not.
无论Logger是否记录了消息,我们都会产生构建消息的成本。
Logback offers an alternative with its parameterized messages:
Logback以其参数化的信息提供了一个替代方案。
log.debug("Current count is {}", count);
The braces {} will accept any Object and uses its toString() method to build a message only after verifying that the log message is required.
大括号{}将接受任何Object,并使用其toString()方法,只有在验证了日志信息是必需的之后,才能建立一个信息。
Let’s try some different parameters:
让我们尝试一些不同的参数。
String message = "This is a String";
Integer zero = 0;
try {
logger.debug("Logging message: {}", message);
logger.debug("Going to divide {} by {}", 42, zero);
int result = 42 / zero;
} catch (Exception e) {
logger.error("Error dividing {} by {} ", 42, zero, e);
}
This snippet yields:
这个片段产生了。
21:32:10.311 [main] DEBUG com.baeldung.logback.LogbackTests - Logging message: This is a String
21:32:10.316 [main] DEBUG com.baeldung.logback.LogbackTests - Going to divide 42 by 0
21:32:10.316 [main] ERROR com.baeldung.logback.LogbackTests - Error dividing 42 by 0
java.lang.ArithmeticException: / by zero
at com.baeldung.logback.LogbackTests.givenParameters_ValuesLogged(LogbackTests.java:64)
...
We see how a String, an int, and an Integer can be passed in as parameters.
我们看到一个字符串,一个int,和一个Integer可以作为参数被传入。
Also, when an Exception is passed as the last argument to a logging method, Logback will print the stack trace for us.
另外,当Exception作为最后一个参数传递给一个日志方法时,Logback将为我们打印堆栈跟踪。
6. Detailed Configuration
6.详细配置
In the previous examples, we were using the 11-line configuration file we created in section 4 to print log messages to the console. This is Logback’s default behavior; if it can’t find a configuration file, it creates a ConsoleAppender and associates it with the root logger.
在前面的例子中,我们使用了在第4节中创建的11行配置文件,将日志信息打印到控制台。这是Logback的默认行为;如果它找不到一个配置文件,它就会创建一个ConsoleAppender ,并将其与根记录器关联。
6.1. Locating Configuration Information
6.1.查找配置信息
A configuration file can be placed in the classpath and named either logback.xml or logback-test.xml.
配置文件可以放在classpath中,命名为logback.xml或logback-test.xml.。
Here’s how Logback will attempt to find configuration data:
下面是Logback试图寻找配置数据的方法。
- Search for files named logback-test.xml, logback.groovy, or logback.xml in the classpath, in that order
- If the library doesn’t find those files, it will attempt to use Java’s ServiceLoader to locate an implementor of the com.qos.logback.classic.spi.Configurator.
- Configure itself to log output directly to the console
Important Note: Due to the official documentation of Logback, they have stopped supporting logback.groovy. So if you want to configure Logback in your application, it’s better to use the XML version.
重要提示。由于Logback的官方文档,他们已经停止支持logback.groovy。所以如果你想在你的应用程序中配置Logback,最好使用XML版本。
6.2. Basic Configuration
6.2.基本配置
Let’s take a closer look at our example configuration.
让我们仔细看看我们的示例配置。
The entire file is in <configuration> tags.
整个文件都在<configuration>tags中。
We see a tag that declares an Appender of type ConsoleAppender, and names it STDOUT. Nested within that tag is an encoder. It has a pattern with what looks like sprintf-style escape codes:
我们看到一个标签,它声明了一个Appender类型的ConsoleAppender,并命名为STDOUT。嵌套在该标签中的是一个编码器。它有一个看起来像sprintf-style转义代码的模式:。
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
Finally, we see a root tag. This tag sets the root logger to DEBUG mode, and associates its output with the Appender named STDOUT:
最后,我们看到一个root标签。这个标签将根记录器设置为DEBUG模式,并将其输出与名为STDOUT的Appender关联。
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
6.3. Troubleshooting Configuration
6.3.故障排除配置
Logback configuration files can get complicated, so there are several built-in mechanisms for troubleshooting.
Logback的配置文件可能会变得很复杂,所以有几个内置的机制来排除故障。
To see debug information as Logback processes the configuration, we can turn on debug logging:
为了在Logback处理配置时看到调试信息,我们可以打开调试日志。
<configuration debug="true">
...
</configuration>
Logback will print status information to the console as it processes the configuration:
Logback在处理配置时,会将状态信息打印到控制台。
23:54:23,040 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml]
at [file:/Users/egoebelbecker/ideaProjects/logback-guide/out/test/resources/logback-test.xml]
23:54:23,230 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender
of type [ch.qos.logback.core.ConsoleAppender]
23:54:23,236 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
23:54:23,247 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type
[ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
23:54:23,308 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to DEBUG
23:54:23,309 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
23:54:23,310 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
23:54:23,313 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@5afa04c - Registering current configuration
as safe fallback point
If warnings or errors are encountered while parsing the configuration file, Logback writes status messages to the console.
如果在解析配置文件时遇到警告或错误,Logback会将状态信息写到控制台。
There is a second mechanism for printing status information:
还有一个打印状态信息的机制。
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
...
</configuration>
The StatusListener intercepts status messages and prints them during configuration, as well as while the program is running.
StatusListener拦截状态信息,并在配置期间以及程序运行时打印出来。
The output from all configuration files is printed, making it useful for locating “rogue” configuration files on the classpath.
所有配置文件的输出都会被打印出来,这对于定位classpath上的 “流氓 “配置文件非常有用。
6.4. Reloading Configuration Automatically
6.4.自动重新加载配置
Reloading logging configuration while an application is running is a powerful troubleshooting tool. Logback makes this possible with the scan parameter:
在应用程序运行时重新加载日志配置是一个强大的故障排除工具。Logback通过scan参数使其成为可能。
<configuration scan="true">
...
</configuration>
The default behavior is to scan the configuration file for changes every 60 seconds. We can modify this interval by adding scanPeriod:
默认行为是每60秒扫描一次配置文件的变化。我们可以通过添加scanPeriod来修改这个时间间隔。
<configuration scan="true" scanPeriod="15 seconds">
...
</configuration>
We can specify values in milliseconds, seconds, minutes, or hours.
我们可以用毫秒、秒、分钟或小时来指定数值。
6.5. Modifying Loggers
6.5.修改记录器
In our sample file above, we set the level of the root logger and associated it with the console Appender.
在我们上面的示例文件中,我们设置了根记录器的级别,并将其与控制台Appender关联。
We can set the level for any logger:
我们可以为任何记录器设置级别。
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.baeldung.logback" level="INFO" />
<logger name="com.baeldung.logback.tests" level="WARN" />
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Let’s add this to our classpath and run the code:
让我们把它添加到我们的classpath中并运行代码。
Logger foobar =
(ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.foobar");
Logger logger =
(ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.logback");
Logger testslogger =
(ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.logback.tests");
foobar.debug("This is logged from foobar");
logger.debug("This is not logged from logger");
logger.info("This is logged from logger");
testslogger.info("This is not logged from tests");
testslogger.warn("This is logged from tests");
We see this output:
我们看到这个输出。
00:29:51.787 [main] DEBUG com.baeldung.foobar - This is logged from foobar
00:29:51.789 [main] INFO com.baeldung.logback - This is logged from logger
00:29:51.789 [main] WARN com.baeldung.logback.tests - This is logged from tests
By not setting the level of our Loggers programmatically, the configuration sets them; com.baeldung.foobar inherits DEBUG from the root logger.
通过不以编程方式设置我们的记录器的级别,配置设置了它们;com.baeldung.foobar 继承DEBUG来自根记录器。
Loggers also inherit the appender-ref from the root logger. As we’ll see below, we can override this.
记录器也从根记录器中继承appender-ref。正如我们将在下面看到的,我们可以覆盖这一点。
6.6. Variable Substitution
6.6.变量替换
Logback configuration files support variables. We define variables inside the configuration script or externally. A variable can be specified at any point in a configuration script in place of a value.
Logback配置文件支持变量。我们在配置脚本内部或外部定义变量。变量可以在配置脚本中的任何一个点上指定,以代替一个值。
For example, here is the configuration for a FileAppender:
例如,这里是一个FileAppender的配置。
<property name="LOG_DIR" value="/var/log/application" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${LOG_DIR}/tests.log</file>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
At the top of the configuration, we declared a property named LOG_DIR. Then we used it as part of the path to the file inside the appender definition.
在配置的顶部,我们声明了一个名为LOG_DIR的属性,然后我们把它作为appender定义内文件路径的一部分。
Properties are declared in a <property> tag in configuration scripts, but they’re also available from outside sources, such as system properties. We could omit the property declaration in this example and set the value of LOG_DIR on the command line:
属性在配置脚本中用<property>标签声明,但它们也可以从外部来源获得,例如系统属性。我们可以在这个例子中省略property声明,在命令行中设置LOG_DIR的值。
$ java -DLOG_DIR=/var/log/application com.baeldung.logback.LogbackTests
We specify the value of the property with ${propertyname}. Logback implements variables as text replacement. Variable substitution can occur at any point in a configuration file where a value can be specified.
我们用${propertyname}来指定属性的值。 Logback实现了变量的文本替换。变量替换可以发生在配置文件中任何可以指定数值的地方。
7. Appenders
7.应用者
Loggers pass LoggingEvents to Appenders. Appenders do the actual work of logging. We usually think of logging as something that goes to a file or the console, but Logback is capable of much more. Logback-core provides several useful appenders.
Loggers将LoggingEvents传递给Appenders. Appenders完成日志的实际工作。我们通常认为日志是指发送到文件或控制台的东西,但Logback的功能远不止这些。Logback-core提供了几个有用的Appenders。
7.1. ConsoleAppender
7.1.ConsoleAppender
We’ve seen ConsoleAppender in action already. Despite its name, ConsoleAppender appends messages to System.out or System.err.
我们已经看到了ConsoleAppender的行动。尽管它的名字叫 “ConsoleAppender”,但它会将信息附加到System.out或System.err.。
It uses an OutputStreamWriter to buffer the I/O, so directing it to System.err doesn’t result in unbuffered writing.
它使用OutputStreamWriter来缓冲I/O,所以将其指向System.err不会导致未缓冲的写入。
7.2. FileAppender
7.2.FileAppender
FileAppender appends messages to a file. It supports a broad range of configuration parameters. Let’s add a file appender to our basic configuration:
FileAppender将信息应用于文件。它支持一系列广泛的配置参数。让我们在我们的基本配置中添加一个文件appender。
<configuration debug="true">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>tests.log</file>
<append>true</append>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.baeldung.logback" level="INFO" />
<logger name="com.baeldung.logback.tests" level="WARN">
<appender-ref ref="FILE" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
The FileAppender is configured with a file name via <file>. The <append> tag instructs the Appender to append to an existing file rather than truncating it. If we run the test several times, we see that the logging output is appended to the same file.
FileAppender通过<file>配置了一个文件名。<append>标签指示Appender追加到一个现有文件,而不是截断它。如果我们多次运行该测试,我们会看到日志输出被追加到同一个文件中。
If we re-run our test from above, messages from com.baeldung.logback.tests go to both the console and to a file named tests.log. The descendant logger inherits the root logger’s association with the ConsoleAppender with its association with FileAppender. Appenders are cumulative.
如果我们重新运行上面的测试,来自com.baeldung.logback.test的消息会同时进入控制台和名为test.log的文件。后裔logger继承了根logger与ConsoleAppender的关联与FileAppender的关联。 Appenders是累积的。
We can override this behavior:
我们可以覆盖这一行为。
<logger name="com.baeldung.logback.tests" level="WARN" additivity="false" >
<appender-ref ref="FILE" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
Setting additivity to false disables the default behavior. Tests won’t log to the console, and neither will any of its descendants.
将additivity设置为false可禁用默认行为。Tests不会记录到控制台,它的任何后代也不会。
7.3. RollingFileAppender
7.3.RollingFileAppender
Often, appending log messages to the same file is not the behavior we need. We want files to “roll” based on time, log file size, or a combination of both.
通常情况下,将日志信息附加到同一个文件中并不是我们需要的行为。我们希望文件能根据时间、日志文件大小或两者的组合来 “滚动”。
For this, we have RollingFileAppender:
为此,我们有RollingFileAppender:。
<property name="LOG_FILE" value="LogFile" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
<!-- keep 30 days' worth of history capped at 3GB total size -->
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
A RollingFileAppender has a RollingPolicy. In this sample configuration, we see a TimeBasedRollingPolicy.
一个RollingFileAppender有一个RollingPolicy.在这个样本配置中,我们看到一个TimeBasedRollingPolicy。
Similar to the FileAppender, we configured this appender with a file name. We declared a property and used it because we’ll be reusing the file name below.
与FileAppender类似,我们用一个文件名来配置这个appender。我们声明了一个属性并使用它,因为我们将在下面重复使用这个文件名。
We defined a fileNamePattern inside the RollingPolicy. This pattern defines not just the name of files, but also how often to roll them. TimeBasedRollingPolicy examines the pattern and rolls at the most finely defined period.
我们在RollingPolicy里面定义了一个fileNamePattern。这个模式不仅定义了文件的名称,而且还定义了滚动的频率。TimeBasedRollingPolicy检查该模式,并在最细微的定义的时期进行滚动。
For example:
比如说。
<property name="LOG_FILE" value="LogFile" />
<property name="LOG_DIR" value="/var/logs/application" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/${LOG_FILE}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/%d{yyyy/MM}/${LOG_FILE}.gz</fileNamePattern>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
The active log file is /var/logs/application/LogFile. This file rolls over at the beginning of each month into /Current Year/Current Month/LogFile.gz and RollingFileAppender creates a new active file.
活动的日志文件是/var/logs/application/LogFile.这个文件在每个月的月初滚动到/Current Year/Current Month/LogFile.gz,RollingFileAppender创造一个新的活动文件。
When the total size of archived files reaches 3GB, RollingFileAppender deletes archives on a first-in-first-out basis.
当归档文件的总大小达到3GB时,RollingFileAppender以先入先出的方式删除归档文件。
There are codes for a week, hour, minute, second, and even millisecond. Logback has a reference here.
有一周、小时、分钟、秒,甚至是毫秒的代码。Logback有一个参考这里。
RollingFileAppender also has built-in support for compressing files. It compresses our rolled files because we named them LogFile.gz.
RollingFileAppender也有对压缩文件的内置支持。它压缩了我们的滚动文件,因为我们把它们命名为LogFile.gz.。
TimeBasedPolicy isn’t our only option for rolling files. Logback also offers SizeAndTimeBasedRollingPolicy, which will roll based on current log file size as well as time. It also offers a FixedWindowRollingPolicy, which rolls log file names each time the logger is started.
TimeBasedPolicy并不是我们滚动文件的唯一选择。Logback还提供了SizeAndTimeBasedRollingPolicy,它将根据当前日志文件的大小和时间来滚动。它还提供了一个FixedWindowRollingPolicy,它在每次启动记录器时都会滚动日志文件名。
We can also write our own RollingPolicy.
我们也可以编写自己的RollingPolicy.。
7.4. Custom Appenders
7.4.自定义Appenders
We can create custom appenders by extending one of Logback’s base appender classes. We have a tutorial for creating custom appenders here.
我们可以通过扩展Logback的一个基础appender类来创建自定义appender。我们有一个创建自定义appender的教程这里。
8. Layouts
8.布局
Layouts format log messages. Like the rest of Logback, Layouts are extensible and we can create our own. However, the default PatternLayout offers what most applications need and then some.
Layouts格式化日志信息。像Logback的其他部分一样,Layouts是可扩展的,我们可以创建我们自己的。然而,默认的PatternLayout提供了大多数应用程序需要的东西,然后还有一些。
We’ve used PatternLayout in all of our examples so far:
到目前为止,我们在所有的例子中都使用了PatternLayout。
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
This configuration script contains the configuration for PatternLayoutEncoder. We pass an Encoder to our Appender, and this encoder uses the PatternLayout to format the messages.
这个配置脚本包含了PatternLayoutEncoder的配置。我们将一个Encoder传递给我们的Appender,并且这个编码器使用PatternLayout来格式化消息。
The text in the <pattern> tag defines how log messages are formatting. PatternLayout implements a large variety of conversion words and format modifiers for creating patterns.
<pattern>标签中的文本定义了日志信息的格式化方式。PatternLayout实现了大量用于创建模式的转换词和格式修改器。
Let’s break this one down. PatternLayout recognizes conversion words with a %, so the conversions in our pattern generate:
让我们来分析一下这个问题。PatternLayout可以识别带有%的转换词,所以我们模式中的转换词会产生。
- %d{HH:mm:ss.SSS} – a timestamp with hours, minutes, seconds and milliseconds
- [%thread] – the thread name generating the log message, surrounded by square brackets
- %-5level – the level of the logging event, padded to 5 characters
- %logger{36} – the name of the logger, truncated to 35 characters
- %msg%n – the log messages followed by the platform dependent line separator character
So we see messages similar to this:
所以我们看到与此类似的信息。
21:32:10.311 [main] DEBUG com.baeldung.logback.LogbackTests - Logging message: This is a String
An exhaustive list of conversion words and format modifiers can be found here.
转换词和格式修饰符的详尽清单可以在这里找到。
9. Conclusion
9.结语
In this extensive article, we covered the fundamentals of using Logback in an application.
在这篇广泛的文章中,我们介绍了在一个应用程序中使用Logback的基本原理。
We looked at the three major components in Logback’s architecture: Logger, Appender, and Layout. Logback has powerful configuration scripts, which we used to manipulate components for filtering and formatting messages. We also discussed the two most commonly used file appenders to create, roll over, organize, and compress log files.
我们看了Logback架构中的三个主要组件。Logger、Appender和Layout。Logback有强大的配置脚本,我们用它来操作过滤和格式化消息的组件。我们还讨论了两个最常用的文件appender,用于创建、翻转、组织和压缩日志文件。
As usual, code snippets can be found over on GitHub.
像往常一样,代码片段可以在GitHub上找到over。