如果你曾经不得不分析生产中的问题,我相信你知道良好的日志记录是多么重要。良好的日志记录需要三件事:
- 日志消息需要提供所需的信息,以了解应用程序在内部执行的操作。
- 编写日志消息必须尽可能高效,这样才不会影响应用程序的性能。
- 您需要能够根据不同的部署环境和情况调整日志详细信息。
虽然您仍然需要自己决定应该为每个用例编写哪些日志消息,但您不需要担心需求2和需求3。各种日志框架已经解决了这些技术要求。您只需要选择其中一个,并使用它来编写日志消息。
为了让它变得更好,SLF4J提供了一个标准化的API,其中大多数框架都以某种方式实现了该API。这使您能够在不更改代码的情况下更改日志框架。只需将依赖关系更改为实现SLF4J接口的不同框架。
使用SLF4J编写日志消息
使用SLF4J编写日志消息非常简单。首先需要调用LoggerFactory
上的getLogger
方法来实例化一个新的Logger
对象。然后,您可以调用记录器上的debug
、info
、warning
、error
或fatal
方法之一,以编写具有相应日志级别的日志消息。这里你可以看到一个典型的例子:
public class MyClass {
Logger log = LoggerFactory.getLogger(this.getClass().getName());
public void myMethod() {
log.info("This is an info message");
// ...
}
}
那么,如果这些框架很容易互换,你应该选择哪一个呢?
这个问题的答案并不像你想象的那么简单。Java世界中广泛使用了几种可用的框架。在本文中,我想向您介绍Log4j及其两个继任者Logback和Log4j2。
Apache Log4J
Apache Log4J是一个非常古老的日志框架,多年来一直是最流行的日志框架。它介绍了一些基本概念,如分层日志级别和日志记录器,这些概念仍然被现代日志框架使用。
开发团队在2015年宣布了Log4j的生命终结。虽然很多遗留项目仍在使用它,但如果您启动一个新项目,您应该更喜欢本文中讨论的其他框架之一。
在我们讨论Logback和Log4j2之前,让我们先快速了解一下所需的依赖项和配置。
必需的依赖项
如果想在应用程序中使用Log4j,需要添加Log4j.jar文件到你的类路径。您可以在下面的代码片段中看到所需的Maven依赖项。
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
Log4j本机不支持SLF4J。您还需要添加以下依赖项,以便能够通过标准化接口使用Log4j。
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
配置Log4j
除了log4j.jar文件,您需要在log4j中定义appender和logger的日志级别。appender将日志消息写入目标,例如文件或数据库。logger和level定义写入日志文件的日志消息的粒度。
下面的代码片段显示了一个应用程序开发系统的典型log4j.properties,该应用程序使用Hibernate作为对象关系映射器。它会将所有日志消息写入文件应用程序。记录并将常规日志级别设置为INFO。该配置还设置记录器组织的日志级别。org.hibernate.type.descriptor.sql
要跟踪的sql到TRACE。这是Hibernate的两个记录器,它们将执行的SQL语句及其绑定参数值写入配置的文件appender。
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=app.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c] - %m%n
log4j.rootLogger=info, file
# basic log level for all messages
log4j.logger.org.hibernate=info
# SQL statements and parameters
log4j.logger.org.hibernate.SQL=debug
log4j.logger.org.hibernate.type.descriptor.sql=trace
基于此配置,您可以使用SLF4J API编写日志消息。这就是Log4j的全部内容。
Logback
Logback由实现Log4j的开发人员编写,其目标是成为其继任者。它遵循与Log4j相同的概念,但被重写是为了提高性能、本机支持SLF4J,以及实现其他一些改进,如高级过滤选项和自动重新加载日志配置。
该框架由三部分组成:
logback-core
logback-classic
logback-access
Logback core提供了日志框架的核心功能。Logback classic为核心功能添加了更多功能,例如对SLF4J的本机支持。logback access将其与servlet容器集成,以便您可以使用它编写HTTP访问日志。
必需的依赖项
您只需要定义对logback classic的依赖。它包括对logback core和SLF4J API的依赖关系。
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
配置Logback
Logback不需要任何配置。默认情况下,它会将调试级别或更高级别的所有日志消息写入标准输出。您可以使用XML或Groovy格式的自定义配置文件来更改这一点。
Logback使用与Log4j相同的概念。因此,即使它们使用不同的文件格式,它们的配置也非常相似,这并不奇怪。下面的代码片段显示的配置与我在Log4j中使用的配置相同。
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>app.log</file>
<encoder>
<pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
</encoder>
</appender>
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
<root level="info">
<appender-ref ref="FILE" />
</root>
</configuration>
在添加了所需的依赖项并配置了Logback之后,可以使用它通过SLF4J API编写日志消息。因此,如果您想从Logback提供的改进中获益,您不需要更改任何代码来用Logback替换Log4j。
现在让我们看看Log4j2。
Apache Log4j2
Apache Log4j2是这三个框架中最年轻的一个,其目标是通过提供自己对Log4j的改进来改进这两个框架,包括Logback中包含的一些改进,并避免Log4j和Logback的问题。
因此,与Logback一样,Log4j2支持SLF4J,自动重新加载日志配置,并支持高级过滤选项。除了这些特性之外,它还允许基于lambda表达式对日志语句进行延迟计算,为低延迟系统提供异步记录器,并提供无垃圾模式以避免垃圾收集器操作造成的任何延迟。
所有这些特性使Log4j2成为这三种日志框架中最先进、最快的。
必需的依赖项
Log4j2将其API和实现打包在两个单独的jar文件中。可以使用log4japi实现和构建应用程序。您需要提供额外的log4j内核。运行时使用jar。如果要使用SLF4JAPI,还需要log4j-slf4j-impl.jar
文件,其中包含两个API之间的桥梁。
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.11.1</version>
</dependency>
配置Log4j2
Log4j2的配置遵循与前面两个日志框架相同的原则,因此看起来非常相似。
<Configuration status="info">
<Appenders>
<File name="FILE" fileName="app.log">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
<Loggers>
<Logger name="org.hibernate.SQL" level="DEBUG">
<AppenderRef ref="FILE"/>
</Logger>
<Logger name="org.hibernate.type.descriptor.sql" level="TRACE">
<AppenderRef ref="FILE"/>
</Logger>
<Root level="info">
<AppenderRef ref="FILE"/>
</Root>
</Loggers>
</Configuration>
结论
Log4j、Logback和Log4j2是广泛使用的良好日志框架。那么你应该用哪一个呢?
我建议使用Log4j2,因为它是三种框架中最快、最先进的。如果性能不是您的最高优先级,那么Logback仍然是一个不错的选择。