Log4j2与Slf4j的最佳实践

简介: 本文将介绍目前Java项目中最常见的Log4j2 + Slf4j的使用组合,这也是我自己项目中目前使用的。

前言


日志对于项目的重要性不言而喻,现在市面上的日志框架多种多样:Log4jLog4j2Slf4jJDKLogLogback等等,如果没有真正深入了解过,可能会被搞得眼花缭乱。本文将介绍目前Java项目中最常见的Log4j2 + Slf4j的使用组合,这也是我自己项目中目前使用的。


另外,由于现在项目基本都是Servlet 3.0及以上版本,因此本文针对Servlet 3.0及更高的版本,如果使用的是Servlet 2.5可以参考官方文档进行适当的调整。


官方文档地址:http://logging.apache.org/log4j/2.x/manual/webapp.html

 

如何查看Servlet版本?


查看web.xml文件中<web-app>标签中的version字段即可。

image.png

 

关于Log4j2


在上面提到的日志框架中,以Log4j + Slf4j的使用组合最为常见,但是我们知道Log4j目前已经停止更新了。Apache推出了新的Log4j2来代替Log4jLog4j2是对Log4j的升级,与其前身Log4j相比有了显着的改进,并提供了许多Logback可用的改进,同时解决了Logback体系结构中的一些固有问题。因此,Log4j2 + Slf4j应该是未来的大势所趋。

 

Log4j2的性能


Log4j2最牛逼的地方在于异步输出日志时的性能表现,Log4j2在多线程的环境下吞吐量与Log4jLogback的比较如下图。下图比较中Log4j2有三种模式:1)全局使用异步模式;2)部分Logger采用异步模式;3)异步Appender。可以看出在前两种模式下,Log4j2的性能较之Log4jLogback有很大的优势。

image.png

Log4j2完整的官方性能文档:http://logging.apache.org/log4j/2.x/performance.html

 

Log4j2使用的几个点


1.    Web项目中需要添加log4j-web jar包。

2.    Log4j允许使用log4jConfiguration参数在web.xml中指定配置文件位置。Log4j将通过以下方式搜索配置文件:

     1.    如果配置了路径(log4jConfiguration参数配置),Log4j将去搜索这个位置。

     2.    如果未配置路径,Log4j将搜索WEB-INF目录中“log4j2”开头的文件。如果找到多个文件,并且存在以“log4j2-name”开头的文件,其中nameWeb应用程序的名称,则会使用它。否则,将使用第一个文件。

     3.    resources目录下搜索配置文件,规则同b


3.    Log4j2不支持Servlet 2.4及更老的的Web应用程序。

2点讲的简单点就是:Log4j2的配置文件名以“log4j2”开头时(例如常见的log4j2.xml),放在WEB-INFresources的根路径时不需要在web.xml中配置路径,放在其他位置时需要配置路径。

 

基本的使用(同步模式)


1.maven依赖


<!--log4j2核心包-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.9.1</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.9.1</version>
</dependency>
<!-- Web项目需添加 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-web</artifactId>
    <version>2.9.1</version>
</dependency>
<!--用于与slf4j保持桥接-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.9.1</version>
</dependency>
<!-- slf4j核心包-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>

 

2.resources根路径下添加log4j2.xml配置文件(无需配置路径)

image.png

logj2.xml文件内容:将info及以上级别的日志输出到Console和指定路径的文件中。

image.png


3.web.xml配置log4j2配置文件的路径


如果log4j2.xml放在WEB-INFresources根路径则不需要。

1.  <!-- log4j2.xml路径 -->

2.  <context-param>

3.      <param-name>log4jConfiguration</param-name>

4.      <param-value>/config/log4j2.xml</param-value>

5.  </context-param>

 

4.如果是从Log4j等其他日志转的Log4j2 + Slf4j的,记得把Mavne中原来日志框架的依赖去掉或exclusion


常见的有:log4jslf4j-log4j12,如下。

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency>

 

5.代码中使用

import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
 * @Author joonwhee
 * @Date 2018/3/31
 */
@Controller
@RequestMapping("/user")
public class UserController {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
    @RequestMapping("/userList")
    public String userList(HttpServletRequest request, Model model) {
        LOGGER.info("Test log4j2 info");
        LOGGER.warn("Test log4j2 warn");
        LOGGER.error("Test log4j2 error");
        return "userList";
    }
}

 

6.使用结果


调用该方法后,Console输出:

image.png

log4j2.xml文件中配置的路径下生成日志文件:

image.png

打开日志查看输出内容:

image.png

这里Console输出和日志文件输出前缀不完全一致是由于上面log4j2.xmlConsoleRollingFilePatternLayout配置不一致导致的。

 

至此,Log4j2集成Slf4j就完成了。

 

扩展测试


关于上面提到的Log4j2配置文件存放路径的问题,我们来做几个简单的测试:


场景1log4j2.xml放在resources/config路径下,在web.xml中配置log4jConfiguration指定路径。

image.png

效果:日志正常输出。

结论:Log4j能找到配置文件。

 

场景2log4j2.xml放在resources/config路径下,注释掉web.xml中的log4jConfiguration配置。

image.png

效果:明显看出我们的配置已经失效了,但是输出了ERROR级别的日志,可以推测这是Log4j在找不到配置文件时的兜底策略。

结论:Log4j不能找到配置文件。

 

场景3log4j2.xml放在resources根路径下,注释掉web.xml中的log4jConfiguration配置。

image.png

效果:日志正常输出。

结论:Log4j能找到配置文件。

 

场景4log4j2.xml放在WEB-INF根路径下,注释掉web.xml中的log4jConfiguration配置。

image.png

效果:日志正常输出。

结论:Log4j能找到配置文件。

 

看完测试结果,大家就可以根据自己的习惯将log4j2.xml放到自己喜欢的地方了。

 

进阶使用(异步模式)


异步模式下,默认情况不会输出位置信息,因为输出位置信息会慢30-100倍。如果需要位置信息,需要在所有相关记录器(包括根记录器)的配置中设置“includeLocation = true”

例如以下代码:

<asyncRoot level="info" includeLocation="true">
    <AppenderRef ref="RandomAccessFile"/>
</asyncRoot>

什么是位置信息?

直接看下面两张图就很明显了。

有位置信息:

image.png

无位置信息:

image.png

 

1.全局使用异步(在同步模式的基础上修改)


1.maven增加disruptor依赖,Log4j2版本2.9及以上时需要disruptor-3.3.4.jar或更高版本;Log4j2版本2.9以下时需要disruptor-3.0.0.jar或更高版本。

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.3.4</version>
</dependency>

2.将系统属性log4j2.contextSelector设置为org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

方式:添加一个名字为log4j2.component.properties的文件,放到classpath下面,log4j2会在启动的时候自动加载。如下:

image.png

image.png

3.log4j2.xml的配置修改成如下,跟同步模式的区别为RollingFile变成了RandomAccessFile

image.png


2.部分Logger采用异步方式(在同步模式的基础上修改)


1.maven增加disruptor依赖,Log4j2版本2.9及以上时需要disruptor-3.3.4.jar或更高版本;Log4j2版本2.9以下时需要disruptor-3.0.0.jar或更高版本。

<dependency>
    <groupId>com.lmax</groupId>
    <artifactId>disruptor</artifactId>
    <version>3.3.4</version>
</dependency>

2.使用<asyncRoot><asyncLogger>配置来指定需要异步的记录器。

<asyncRoot level="info">
    <AppenderRef ref="RandomAccessFile"/>
</asyncRoot>

3.log4j2.xml的配置修改成如下,跟同步模式的区别为:1RollingFile变成了RandomAccessFile2loggers中使用了<asyncRoot><asyncLogger>

image.png

注意:配置只能包含一个根记录器(<root><asyncRoot>元素),但可以组合异步和非异步记录器。例如,包含<asyncLogger>元素的配置文件也可以包含同步记录器的<Root><Logger>元素。

 

异步模式完整的官方文档地址:http://logging.apache.org/log4j/2.x/manual/async.html

 

简单性能测试


简单的测试下以下三种模式的耗时:全局使用异步的Log4j2、部分Logger使用异步的Log4j2、使用同步模式的Log4j2


测试代码


1.测试例子很简单,就是将之前的3行输出外面加个64万次的循环。

image.png

2.将输出Console去掉,只输出到文件,同步模式下的AppendersRollingFile;异步模式下的AppendersRandomAccessFile

 

场景1RollingFile +同步模式不带位置信息


场景1的配置文件主要内容如下

image.png

测试结果如下图:总共耗时17678ms

image.png

image.png



场景2RollingFile +同步模式带位置信息


场景2的配置文件主要内容如下,跟场景1只有includeLocation属性值不同

image.png

测试结果如下图:总共耗时257268ms

image.png

场景3RandomAccessFile + 全局使用异步


场景3的配置文件主要内容如下

image.png

image.png

测试结果如下图:总共耗时2303ms

image.png


场景4RandomAccessFile + 部分使用异步


场景4的配置文件主要内容如下

image.png

测试结果如下图:总共耗时5864ms

image.png

输出384万行简单日志的测试结果统计:

以上测试只是简单的测试,仅供参考,详细的性能比较可以查看官方文档:http://logging.apache.org/log4j/2.x/performance.html

 

结论:


1.    通过测试结果可以看出,Log4j2的异步模式性能提升还是比较明显的,但是需根据实际情况来确认是否需要。正常项目使用同步模式一般都够用了。

2.    输出位置信息带来的性能损耗太高了。因此,在线上项目的日志记录一定不要输出位置信息。

相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
相关文章
|
5月前
|
Prometheus 监控 Java
日志收集和Spring 微服务监控的最佳实践
在微服务架构中,日志记录与监控对系统稳定性、问题排查和性能优化至关重要。本文介绍了在 Spring 微服务中实现高效日志记录与监控的最佳实践,涵盖日志级别选择、结构化日志、集中记录、服务ID跟踪、上下文信息添加、日志轮转,以及使用 Spring Boot Actuator、Micrometer、Prometheus、Grafana、ELK 堆栈等工具进行监控与可视化。通过这些方法,可提升系统的可观测性与运维效率。
555 1
日志收集和Spring 微服务监控的最佳实践
|
5月前
|
负载均衡 监控 安全
5 个 IIS 日志记录最佳实践
IIS日志记录是监控Web服务器性能与安全的关键。本文介绍启用日志、应用池配置、负载均衡、敏感数据防护、日志集中管理及保留策略等五大最佳实践,助力高效分析与合规审计。
370 1
|
11月前
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
2749 1
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
4359 31
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
11月前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录——使用Logger在项目中打印日志
本文介绍了如何在项目中使用Logger打印日志。通过SLF4J和Logback,可设置不同日志级别(如DEBUG、INFO、WARN、ERROR)并支持占位符输出动态信息。示例代码展示了日志在控制器中的应用,说明了日志配置对问题排查的重要性。附课程源码下载链接供实践参考。
1247 0
|
11月前
|
SQL Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— application.yml 中对日志的配置
在 Spring Boot 项目中,`application.yml` 文件用于配置日志。通过 `logging.config` 指定日志配置文件(如 `logback.xml`),实现日志详细设置。`logging.level` 可定义包的日志输出级别,例如将 `com.itcodai.course03.dao` 包设为 `trace` 级别,便于开发时查看 SQL 操作。日志级别从高到低为 ERROR、WARN、INFO、DEBUG,生产环境建议调整为较高级别以减少日志量。本课程采用 yml 格式,因其层次清晰,但需注意格式要求。
1075 0
|
11月前
|
Java API 开发者
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录——slf4j 介绍
在软件开发中,`System.out.println()`常被用于打印信息,但大量使用会增加资源消耗。实际项目推荐使用slf4j结合logback输出日志,效率更高。Slf4j(Simple Logging Facade for Java)是一个日志门面,允许开发者通过统一方式记录日志,无需关心具体日志系统。它支持灵活切换日志实现(如log4j或logback),且具备简洁占位符和日志级别判断等优势。阿里巴巴《Java开发手册》强制要求使用slf4j,以保证日志处理方式的统一性和维护性。使用时只需通过`LoggerFactory`创建日志实例即可。
757 0
|
9月前
|
监控 容灾 算法
阿里云 SLS 多云日志接入最佳实践:链路、成本与高可用性优化
本文探讨了如何高效、经济且可靠地将海外应用与基础设施日志统一采集至阿里云日志服务(SLS),解决全球化业务扩展中的关键挑战。重点介绍了高性能日志采集Agent(iLogtail/LoongCollector)在海外场景的应用,推荐使用LoongCollector以获得更优的稳定性和网络容错能力。同时分析了多种网络接入方案,包括公网直连、全球加速优化、阿里云内网及专线/CEN/VPN接入等,并提供了成本优化策略和多目标发送配置指导,帮助企业构建稳定、低成本、高可用的全球日志系统。
983 55
|
10月前
|
监控 安全 BI
优化 Apache 日志记录的 5 个最佳实践
Apache 日志记录对于维护系统运行状况和网络安全至关重要,其核心包括访问日志与错误日志的管理。通过制定合理的日志策略,如选择合适的日志格式、利用条件日志减少冗余、优化日志级别、使用取证模块提升安全性及实施日志轮换,可有效提高日志可用性并降低系统负担。此外,借助 Eventlog Analyzer 等专业工具,能够实现日志的高效收集、可视化分析与威胁检测,从而精准定位安全隐患、评估服务器性能,并满足合规需求,为强化网络安全提供有力支持。
272 0
优化 Apache 日志记录的 5 个最佳实践
|
数据采集 监控 Java
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......
本文是关于SpringBoot日志的详细教程,涵盖日志的定义、用途、SLF4J框架的使用、日志级别、持久化、文件分割及格式配置等内容。
1202 2
SpringBoot日志全方位超详细手把手教程,零基础可学习 日志如何配置及SLF4J的使用......