使用Slf4j集成Log4j2构建项目日志系统的完美解决方案

一、背景

  最近因为公司项目性能需要,我们考虑把以前基于的log4j的日志系统重构成基于Slf4j和log4j2的日志系统,因为,使用slf4j可以很好的保证我们的日志系统具有良好的兼容性,兼容当前常见几种日志系统,而使用log4j2而不是log4j是因为Log4j 1.x 在高并发情况下出现死锁导致cpu使用率异常飙升,而Log4j2.0基于LMAX Disruptor的异步日志在多线程环境下性能会远远优于Log4j 1.x和logback(官方数据是10倍以上)。

  关于slf4j的原理以及优点,请参见我的另一篇博客:slf4j介绍以及实现原理窥探

二、搭建步骤

  1.依赖管理

    1).删除项目中存在的Log4j1.x所必须的log4j和slf4j-log4j12等依赖。

      可以到项目的根目录,执行:mvn dependency:tree > tree.log,之后使用 cat tree.log | grep log4j命令进行查找。

 1     <exclusions>
 2         <exclusion>
 3             <groupId>org.slf4j</groupId>
 4             <artifactId>slf4j-log4j12</artifactId>
 5         </exclusion>
 6         <exclusion>
 7             <groupId>log4j</groupId>
 8             <artifactId>log4j</artifactId>
 9         </exclusion>
10     </exclusions>  

    2).添加以下slf4j和log4j2的依赖.

 1     <!-- slf4j核心包-->
 2         <dependency>
 3             <groupId>org.slf4j</groupId>
 4             <artifactId>slf4j-api</artifactId>
 5             <version>1.7.13</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>org.slf4j</groupId>
 9             <artifactId>jcl-over-slf4j</artifactId>
10             <version>1.7.13</version>
11             <scope>runtime</scope>
12         </dependency>
13
14         <!--核心log4j2jar包-->
15         <dependency>
16             <groupId>org.apache.logging.log4j</groupId>
17             <artifactId>log4j-api</artifactId>
18             <version>2.4.1</version>
19         </dependency>
20         <dependency>
21             <groupId>org.apache.logging.log4j</groupId>
22             <artifactId>log4j-core</artifactId>
23             <version>2.4.1</version>
24         </dependency>
25         <!--用于与slf4j保持桥接-->
26         <dependency>
27             <groupId>org.apache.logging.log4j</groupId>
28             <artifactId>log4j-slf4j-impl</artifactId>
29             <version>2.4.1</version>
30         </dependency>
31         <!--web工程需要包含log4j-web,非web工程不需要-->
32         <dependency>
33             <groupId>org.apache.logging.log4j</groupId>
34             <artifactId>log4j-web</artifactId>
35             <version>2.4.1</version>
36             <scope>runtime</scope>
37         </dependency>
38
39         <!--需要使用log4j2的AsyncLogger需要包含disruptor-->
40         <dependency>
41             <groupId>com.lmax</groupId>
42             <artifactId>disruptor</artifactId>
43             <version>3.2.0</version>
44         </dependency>  

  2.web.xml中设置log4j2的监听器和过滤器(servlet3.0及以上版本不需要该步操作)

 1 <!--对于log4j2,Servlet2.5以前的版本需要-->
 2   <listener>
 3      <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
 4   </listener>
 5   <filter>
 6      <filter-name>log4jServletFilter</filter-name>
 7      <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
 8   </filter>
 9   <filter-mapping>
10      <filter-name>log4jServletFilter</filter-name>
11      <url-pattern>/*</url-pattern>
12      <dispatcher>REQUEST</dispatcher>
13      <dispatcher>FORWARD</dispatcher>
14      <dispatcher>INCLUDE</dispatcher>
15      <dispatcher>ERROR</dispatcher>
16   </filter-mapping>  

  注意:log4j2不再支持properties文件了,只支持xml,json或是yaml,不指定位置的情况下默认在src/main/resources下查找。

     如果需要自定义位置,需要在上面的web.xml中添加以下代码

1 <context-param>
2   <param-name>log4jConfiguration</param-name>
3   <param-value>/WEB-INF/classes/log4j2.xml</param-value>
4 </context-param> 

  3.log4j2.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2
 3 <Configuration status="off" monitorInterval="1800">
 4
 5     <properties>
 6         <property name="LOG_HOME">/opt/logs/hafiz/log4j2Demo/logs</property>
 7         <property name="ERROR_LOG_FILE_NAME">error</property>
 8     </properties>
 9
10
11     <Appenders>
12         <Console name="Console" target="SYSTEM_OUT">
13             <PatternLayout pattern="%d %-5p (%F:%L) - %m%n" />
14         </Console>
15
16         <RollingRandomAccessFile name="ErrorLog"
17                                  fileName="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log"
18                                  filePattern="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log.%d{yyyy-MM-dd}.gz">
19             <PatternLayout
20                     pattern="%d %-5p (%F:%L) - %m%n"/>
21             <Policies>
22                 <TimeBasedTriggeringPolicy/>
23                 <SizeBasedTriggeringPolicy size="100 MB"/>
24             </Policies>
25             <DefaultRolloverStrategy max="20"/>
26         </RollingRandomAccessFile>
27
28     </Appenders>
29
30     <Loggers>
31         <!-- 3rdparty Loggers -->
32         <logger name="org.springframework.core" level="info">
33         </logger>
34         <logger name="org.springframework.beans" level="info">
35         </logger>
36         <logger name="org.springframework.context" level="info">
37         </logger>
38         <logger name="org.springframework.web" level="info">
39         </logger>
40
41         <logger name="com.hafiz.www.controller" level="error" includeLocation="true" additivity="false">
42             <appender-ref ref="ErrorLog"/>
43             <appender-ref ref="Console"/>
44         </logger>
45
46         <root level="info" includeLocation="true">
47             <appender-ref ref="Console"/>
48         </root>
49     </Loggers>
50 </Configuration>  

  4.测试类UserController.java

 1 package com.hafiz.www.controller;
 2
 3 import com.hafiz.www.po.UserEntity;
 4 import com.hafiz.www.service.UserService;
 5 import org.slf4j.Logger;
 6 import org.slf4j.LoggerFactory;
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.stereotype.Controller;
 9 import org.springframework.web.bind.annotation.RequestMapping;
10 import org.springframework.web.bind.annotation.RequestMethod;
11 import org.springframework.web.bind.annotation.ResponseBody;
12
13 import java.util.ArrayList;
14 import java.util.List;
15
16 /**
17  * Desc:用户信息控制器
18  * Created by hafiz.zhang on 2016/8/27.
19  */
20 @Controller
21 @RequestMapping("/user")
22 public class UserController {
23
24     private static final Logger logger = LoggerFactory.getLogger(UserController.class);
25
26     @Autowired
27     private UserService userService;
28
29     @RequestMapping(value = "/all", method = RequestMethod.GET)
30     @ResponseBody
31     public List<UserEntity> getAllUsers(){
32         logger.info("[GET] /user/all getAllUsers");
33         List<UserEntity> list = userService.getAllUsers();
34         logger.debug("This is log of level of debug");
35         logger.trace("log4j2 Demo");
36         logger.error("哎呀,出错啦~");
37         return list;
38     }
39 }

注意:在JVM启动参数中增加 -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector 开启异步日志.

时间: 2024-10-24 11:26:32

使用Slf4j集成Log4j2构建项目日志系统的完美解决方案的相关文章

java项目日志系统的总结

目录 日志系统归类以及关系 日志的三个组件 slf4j的使用 项目中构建日志系统 使用例子 日志系统归类以及关系 常用的日志框架: slf4j.logback .log4j.log4j2.JUL(java util logging).jboss-logging.JCL(jakarta common logging) log4j: 最开始的一个日志系统. JUL: jdk自带的日志系统 jboss-logging: jboss公司的日志系统 JCL: apache 开源的日志框架 slf4j: 基

利用开源架构ELK构建分布式日志系统

本文介绍了如何使用成熟的经典架构ELK(即Elastic search,Logstash和Kibana)构建分布式日志监控系统,很多公司采用该架构构建分布式日志系统,包括新浪微博,freewheel,畅捷通等. 背景日志,对每个系统来说,都是很重要,又很容易被忽视的部分.日志里记录了程序执行的关键信息,ERROR和WARNING信息等等.我们可以根据日志做很多事情,做数据分析,系统监控,排查问题等等 .但是,任何一个中大型系统都不可能是单台Server,日志文件散落在几十台甚至成千上万台Serv

记一次项目上线后Log4j2不输出日志的坑

公司项目采用了Log4j2来输出日志,在开发环境和测试环境下均可以输出日志,但在生成环境就没有日志输出.开始毫无头绪,后来通过不断的排查,终于解决了这个问题.在此记录下该问题的解决过程,便于后续查阅. 一.发现问题 p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; line-height: 125%; font-family: "Times New Roman"; font-size: 12.

6 个 K8s 日志系统建设中的典型问题,你遇到过几个?

作者 |? 元乙? 阿里云日志服务数据采集客户端负责人,目前采集客户端 logtail 在集团百万规模部署,每天采集上万应用数 PB 数据,经历多次双 11.双 12 考验. 导读:随着 K8s 不断更新迭代,使用?K8s 日志系统建设的开发者,逐渐遇到了各种复杂的问题和挑战.本篇文章中,作者结合自己多年经验,分析 K8s 日志系统建设难点,期待为读者提供有益参考. 在 Logging 这块做了几年,最近 1 年来越来越多的同学来咨询如何为 Kubernetes 构建一个日志系统,或者是来求助在

使用 SLF4J + LogBack 构建日志系统(转)

转载自:http://www.cnblogs.com/mailingfeng/p/3499436.html 上次我们讨论了如何选择一个好的开源日志系统方案,其中的结论是:使用 SLF4J + LogBack 是一个很好的选择.这篇文章就来讲讲如何快速地搭建起这套日志系统. 一.简介 LogBack是一个日志框架,它与Log4j可以说是同出一源,都出自Ceki Gülcü之手.(log4j的原型是早前由Ceki Gülcü贡献给Apache基金会的) LogBack.Slf4j.Log4j 之间的

面试题:应用中很多jar包,比如spring、mybatis、redis等等,各自用的日志系统各异,怎么用slf4j统一输出?

一.问题概述 如题所说,后端应用(非spring boot项目)通常用到了很多jar包,比如spring系列.mybatis.hibernate.各类连接数据库的客户端的jar包.可能这个jar包用的是logback.那个用的是log4j.那个又是log4j2, 这时候,怎么才能保证各jar包的日志都能输出,且能以统一的格式输出呢? 为什么要强调非spring boot项目,可参考第四节. 二.几种日志框架的简单介绍 来源:https://juejin.im/post/5a7c5d5751882

基于sentry的前端错误监控日志系统(部署sentry服务器/前端项目部署)-让前端最快的定位到生产问题

背景 在这越来越发达的网络时代,web应用也是越来越复杂,尤其是前端的开发,也是越来越受重视. 所以在我们前端开发完成后,会有一些列的web应用的上线验证,如自测.QA测试.code review 等,以确保 应用能在生产上没有事故. 但是事以愿违,很多时候我们都会接受的客户的一些线上问题,这些问题有时候可能你是自己开发的原因本身存 在的问题,这样的问题一般能够在测试环境重现,我们很快的能定位到问题关键位置.但是,很多时候有一些问题, 我们在测试中并未发现,可是在线上却有部分人出现了,问题确确实

slf4j结合log4j配置日志系统

首先这两个都是日志系统 只不过slf4j是一个简单的门面日志系统简单的来说就是提供了一些列日志接口没有具体的实现类似于jdbc但是比jdbc简单因为 它不需要加载驱动只需要加入其特定的包即可.而log4j自己单独就可以是一个完整的日志系统它提供了自己的实现而不是简单 提供日志接口.下面说说二者的整合. 1.新建一个Java project 2.引入log4j-1.2.15.jar,slf4j-api-1.5.6.jar,slf4j-log4j12-1.5.6.jar三个包 版本不限 3.在项目的

Slf4j与其他日志系统兼容的使用

java生产的各种框架(如spring等)里各个框架会使用不同的日志体系,多个不同日志在一个jvm里混搭会出现一定问题 ,这里梳理一下java体系里常见的日志框架,以SFL4j为中心介绍下跟各个日志框架的关系,介绍下生产环境如何打理各种日志框架. 1. 接口简介 在java的体系里,主要有slf4j和common-logging两种日志体系接口.实现的框架有很多,主流的诸如logback.log4j等. 当然,虽然都是接口,但两者也可以通过桥接包实现相互的日志代理输出. common-loggi