log4j 替代品:java Logback 教程

log4j 替代品:java Logback 教程Logback旨在作为log4j项目的继承者,由Ceki Gülcü设计。与所有现有的日志系统相比,Logback的速度更快,占地面积更小。在特定的关键执行路径上,Logback的表现比Log4j快十

Logback旨在作为log4j项目的继承者,由Ceki Gülcü设计。与所有现有的日志系统相比,Logback的速度更快占地面积更小。在特定的关键执行路径上,Logback的表现比Log4j快十倍左右。

logback-classic中的Logger 类原生地实现了SLF4J的API,所以当我们以logback-classic作为底层实现来调用SLF4J的记录器时,会产生零开销。使用SLF4J API极大地减少了切换日志框架的工作

1.Logback的依赖性

要运行logback,需要在应用程序的运行时间中使用三个模块。

  • logback-core:提供其他两个模块所需的主要类和接口。
  • logback-classic: 原生实现了SLF4J的API。
  • slf4j-api: logback-classic的Logger类实现了SLF4J API。所以我们可以随时在logback和其他日志框架之间来回切换。
  • logback-access(可选):与Servlet容器集成,如Tomcat和Jetty,以提供远程日志功能。
<dependency>
	<groupId>ch.qos.logback</groupId>
	<artifactId>logback-core</artifactId>
	<version>1.2.10</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.10</version>
</dependency>
<dependency>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-api</artifactId>
	<version>1.7.32</version>
</dependency>

注意,logback-classic 会自动拉入logback-coreslf4j-api ,所以添加 logback-classic 依赖关系即可。

2.开始使用Logback

2.1.创建和使用记录仪

在依赖关系被导入classpath后,我们可以开始在应用程序中记录日志。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
	public static void main(final String[] args) 
	{
		Logger logger = LoggerFactory.getLogger(Main.class);
		// OR 
		// Logger logger = LoggerFactory.getLogger("com.howtodoinjava.demo");

		logger.info("Info Message Logged !!!");
	}
}
18:40:47.392 [main] INFO  com.howtodoinjava.demo.slf4j.Main - Info Message Logged !!!

注意上面的类Main 。它导入了SLF4J API中定义的LoggerLoggerFactory类。我们使用静态方法LoggerFactory.getLogger() ,获得Logger实例。然后我们使用logger.info()来记录信息。它支持debug(),info(),*warn()error()*方法。

getLogger() 方法可以接受两种类型的参数,即一个class 类型和一个String 。这两个方法都会返回一个与参数相对应的命名的记录器。

注意我们没有使用任何logback的特定包或类。这样,我们对logback没有直接的依赖性,可以在不改变代码的情况下被其他日志库所取代。

2.2.参数化的消息

在实际应用中,日志信息并不总是纯字符串。我们需要将上下文数据记录到文件中,如对象ID、自定义错误信息和代码等。

这些复杂的消息一般是通过附加字符串来创建的,这涉及到分配内存、串联操作,最后在消息打印完毕、对象不在使用时进行垃圾回收。

有时,上述的字符串连接操作可能没有必要。例如,如果我们将日志级别设置为INFO,那么给定的调试日志将不会被打印在日志文件中,但无论如何,字符串连接都会发生。这样的字符串连接是开销,应该被避免

logger.info("Article fecthed for id : " + 1 + " is : " + a.toString());

Logback用参数化的消息消除了不需要的串联。这些消息使用大括号{} ,作为消息中要打印的对象的占位符。

一旦Logback确定需要打印日志消息,它就会通过串联原始消息并将大括号替换为object.toString() 方法的输出来建立日志消息。

logger.info("Article fecthed for id : {} is : {}", 1, article);

我们可以使用参数化的消息来打印任何类型的对象或信息,包括异常堆栈跟踪。

3.Logback配置

现有的log4j用户可以使用我们的PropertiesTranslator网络应用程序将他们的log4j.properties文件转换成logback.xml。

3.1.零配置默认值

默认情况下,当没有找到默认的配置文件时,logback将在根记录器中添加一个ConsoleAppender ,这将在控制台中记录所有的消息。

输出的格式是使用PatternLayoutEncoder设置为’%d{HH:mm:ss.SSS}的模式。[%thread] %-5level %logger{36}。%msg%n“。另外,默认情况下,根记录器被分配为DEBUG级别。

这是默认使用的等效配置。

<configuration debug="true">
  <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>

3.2.加载配置文件

默认的配置足以让我们开始使用并用于POC目的。但对于生产级的应用,我们需要在合适的日志级别上配置不同的文件记录器。

在启动过程中,logback尝试在classpath中找到logback-test.xmllogback.xml ,顺序相同。如果找到该文件,它将使用提供的配置文件进行自我配置。

如果classpath中没有这样的文件,它就试图通过查找classpath中的META-INF\services\ch.qos.logback.classic.spi.Configurator文件来定位com.qos.logback.classic.spi.Configurator接口的实现,进行程序化配置

如果没有找到该文件或Configurator的实现,它就会用默认配置进行自我配置,如前所述。

注意,可以用一个名为 “logback.configurationFile“的系统属性启动参数指定默认配置文件的位置。这个属性的值可以是一个URL、classpath上的资源或应用程序外部文件的路径。

3.3.检查初始化错误

如果我们在logback初始化过程中面临任何错误,我们可以在configuration 标签中设置debug="true" 。这将在处理配置时向控制台打印状态信息。

请看给定配置文件在控制台打印的状态信息。我们已经创建了appender STDOUT,但在根记录器中,我们把名称定为STDOUT_ONE。打印的日志在控制台中突出了这个配置问题,信息是无法找到名为[STDOUT1]的appender

<configuration debug="true">
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    ...
  </appender>

  <root level="debug">
    <appender-ref ref="STDOUT_ONE" />
  </root>
</configuration>
18:34:34,556 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
18:34:34,556 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/C:/devsetup/gitrepo/opensource-examples/target/classes/logback.xml]
18:34:34,675 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
18:34:34,679 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
18:34:34,686 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
18:34:34,708 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to DEBUG
18:34:34,708 |-ERROR in ch.qos.logback.core.joran.action.AppenderRefAction - Could not find an appender named [STDOUT1]. Did you define it below instead of above in the configuration file?
18:34:34,708 |-ERROR in ch.qos.logback.core.joran.action.AppenderRefAction - See http://logback.qos.ch/codes.html#appender_order for more details.
18:34:34,708 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
18:34:34,710 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@ec756bd - Registering current configuration as safe fallback point
18:34:34,712 |-WARN in Logger[com.howtodoinjava.demo.slf4j.Main] - No appenders present in context [default] for logger [com.howtodoinjava.demo.slf4j.Main].

3.4.修改后自动重新加载配置文件

scan="true" 设置为配置标签,让 logback 扫描更改,并在配置文件更改时自动重新配置。

在后台,一个 *ReconfigureOnChangeTask*在一个单独的线程中运行,并在一个定义的时间间隔内检查配置文件。如果最新版本的配置文件有XML语法错误,它将返回到没有XML语法错误的前一个配置文件。

默认情况下,配置文件将每分钟扫描一次变化。要指定不同的扫描周期,请设置scanPeriod 属性。

<configuration scan="true" scanPeriod="120 seconds" > 
  ...
</configuration>  

如果没有指定时间单位,那么时间单位就假定为毫秒

3.5.条件性配置

与其为不同的需求定义多个配置文件,我们可以把所有的配置放在一个文件中,并借助if,thenelse 标签在相关部分周围添加条件。

例如,给定的配置将在本地开发环境中配置一个控制台appender,并启用调试日志。否则,根记录器将在提供的文件中附加记录所有错误信息。

  <if condition='property("ENV").contains("localhost")'>
    <then>
      <appender name="CON" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
          <pattern>%d %-5level %logger{35} - %msg %n</pattern>
        </encoder>
      </appender>
      <root level="DEBUG">
        <appender-ref ref="CON" />
      </root>
    </then>
  </if>

  <root level="ERROR">
     <appender-ref ref="FILE" />
  </root>

注意,条件处理需要Janino库

4.配置应用者

Logback将编写日志事件的任务委托给称为Appenders的组件。Appenders负责将日志事件以合适的格式输出到合适的输出设备上。然而,他们可以将事件的实际格式化委托给LayoutEncoder对象。

logback配置文件的非常基本的结构可以描述为configuration 元素,包含零个或多个appender 元素,后面是零个或多个logger 元素,后面是最多一个root 元素。

配置文件必须是一个格式良好的XML文件,所有开放的标签必须被正确关闭。

与显式规则有关的标签名称是不区分大小写的。很少有与隐式规则相关的标签是区分大小写的,除了第一个字母。因此,如果作为一个最佳实践,只需遵循camelCase惯例,这几乎总是正确的惯例。

4.1.控制台附加器(ConsoleAppender

控制台appender在控制台,或者更准确的说是在System.outSystem.err上进行追加。

Logback,默认情况下,将控制台应用程序配置为DEBUG级别。我们可以通过在logback.xml文件中定义appender来配置其属性。

<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="INFO">
	<appender-ref ref="STDOUT" />
</root>

4.2.滚动文件Appender

文件附加器将日志事件附加到一个文件中。如果文件已经存在,它要么被追加到,要么被截断,这取决于append 属性的值。

为了记录到滚动文件(基于时间、日志文件大小或两者的组合),我们使用RollingFileAppenderRollingPolicy 负责进行滚动所需的操作,TriggeringPolicy 决定是否发生滚动以及确切的时间。

RollingPolicy实现了TriggeringPolicy接口,所以如果我们只定义rollingPolicy ,那么也将接受配置。

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
	<file>${LOG_ROOT}/app.log</file>
	<append>true</append>
	<immediateFlush>false</immediateFlush>
	<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
		<!-- Archiving daily -->
		<fileNamePattern>${LOG_ROOT}/app-%d{yyyy-MM-dd}.log.gz</fileNamePattern>
		<!-- Archiving 60 days of logs and max 10GB size limit -->
		<maxHistory>60</maxHistory>
		<totalSizeCap>10GB</totalSizeCap>
	</rollingPolicy>
	<encoder>
		<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n
		</pattern>
	</encoder>
</appender>

<root level="INFO">
	<appender-ref ref="FILE" />
</root>

Logback的FileAppender和它的所有子类,包括RollingFileAppender可以从I/O故障中优雅地恢复。因此,如果一个文件服务器暂时发生故障,我们不再需要重新启动应用程序来使日志记录再次工作。只要文件服务器恢复正常,记录器就会重新工作。

通过RollingFileAppender,压缩总是异步发生的,所以即使是大的日志文件,应用程序也不会在压缩的过程中被阻塞

默认情况下,每个日志事件都会立即刷新到底层输出流。在日志吞吐量非常高的情况下,我们可以将immediateFlush 属性设置为假。

5.常见问题

5.1.如何在日志中打印Jar文件名

一旦配置好,logback可以在其输出的堆栈跟踪行中的每一行都包括打包数据(jar文件的名称和版本)。它可以帮助调试识别由于classpath中任何库的多个版本的jar而导致的ClassCastException问题。

默认情况下,打包数据是禁用的。

<configuration packagingData="true">
  ...
</configuration>

5.2.关机时清理资源

在独立的应用程序中,为了正确关闭logback并释放相关资源,请使用shutdown钩子。该钩子将关闭连接到由上下文定义的记录器的所有附加器,并有序地停止任何活动线程。它将允许在后台运行的任何日志文件压缩任务在30秒内完成。

<configuration debug="false">
	<shutdownHook/>
	.... 
</configuration>

关闭钩子将被自动安装在Web应用程序中,使这个指令完全是多余的。

6.总结

在这个Logback教程中,我们学习了默认提供的配置,根据要求定制默认值,并对任何初始化错误进行故障排除。我们学会了配置基本的控制台appender和滚动文件appender。我们将在以后的文章中深入学习这两点。

我们还看到了可以帮助最有效地使用Logback的最佳实践。

学习愉快!!

下载源代码

今天的文章log4j 替代品:java Logback 教程分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/17214.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注