如果您曾经不得不分析生产中的问题,我相信您知道拥有良好的日志记录是多么重要。良好的日志记录需要三件事:
虽然您仍然需要自己决定应该为每个用例编写哪些日志消息,但您不必担心需求 2 和 3。各种日志框架已经解决了这些技术需求。您只需要选择其中之一并使用它来编写日志消息。
为了让它变得更好,SLF4J 提供了一个标准化的 API,这些 API 以一种或另一种方式由大多数框架实现。这使您可以在不更改代码的情况下更改日志记录框架。您只需要将依赖项更改为实现 SLF4J 接口的不同框架。
提示:使用 Stackify Retrace 立即查找应用程序错误和性能问题 借助集成的错误、日志和代码级性能洞察,可以轻松地对代码进行故障排除和优化。使用 SLF4J 编写日志消息非常简单。首先,您需要调用getLogger方法上的LoggerFactory实例化一个新的记录器对象。然后,您可以调用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是一个非常古老的日志框架,多年来一直是最受欢迎的框架。它介绍了现代日志框架仍在使用的基本概念,例如分层日志级别和记录器。
开发团队在 2015 年宣布 Log4j 的生命周期结束。虽然很多遗留项目仍在使用它,但如果您开始一个新项目,您应该更喜欢本文中讨论的其他框架之一。
Matt 在之前的文章中已经非常详细地解释了 Log4j ,您可以使用我之前向您展示的 SLF4JAPI 来使用 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.jar文件之外,您还需要在log4j.properties文件中定义附加程序和记录器及其日志级别。appender 将日志消息写入一个目的地,比如文件或数据库。记录器和级别定义了写入日志文件的日志消息的粒度。
以下代码片段显示了使用 Hibernate 作为对象关系映射器的应用程序开发系统的典型 Log4j 配置。它将所有日志消息写入文件app.log并将一般日志级别设置为 INFO。该配置还将记录器org.hibernate.SQL的日志级别设置为 DEBUG,并将类别org.hibernate.type.descriptor.sql 设置为 TRACE。这些是 Hibernate 的 2 个记录器,它们将执行的 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 的全部内容。如果您想了解更多信息,请查看 Matt Watson 的Ultimate Log4j 教程。
Logback 是由实现 Log4j 的同一位开发人员编写的,目标是成为它的继任者。它遵循与 Log4j 相同的概念,但被重写以提高性能,以原生支持 SLF4J,并实现其他一些改进,如高级过滤选项和日志配置的自动重新加载。
该框架由3部分组成:
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 不需要任何配置。默认情况下,它将调试级别或更高级别的所有日志消息写入标准输出。您可以使用 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 提供的改进中受益,则无需更改任何代码即可将 Log4j 替换为 Logback。
现在让我们来看看 Log4j2。如果您想了解更多关于 Logback 的信息,请查看 Eugen对此的深入文章。
Apache Log4j2是这三个框架中最年轻的一个,它的目标是通过提供自己对 Log4j 的改进来改进这两个框架,包括 Logback 中包含的一些改进以及避免 Log4j 和 Logback 的问题。
因此与 Logback 一样,Log4j2 提供对 SLF4J 的支持,自动重新加载您的日志记录配置,并支持高级过滤选项。除了这些特性之外,它还允许基于 lambda 表达式对日志语句进行延迟评估,为低延迟系统提供异步记录器,并提供无垃圾模式以避免垃圾收集器操作引起的任何延迟。
所有这些特性使 Log4j2 成为这三个日志框架中最先进和最快的。
Log4j2 将其 API 和实现打包在两个单独的 jar 文件中。您可以使用log4j-api.jar实现和构建您的应用程序,并且您需要在运行时提供额外的log4j-core.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 的配置遵循与之前两个日志框架的配置相同的原则,因此看起来非常相似。
<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 仍然是一个不错的选择。