使用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命令进行查找。
- <exclusions>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </exclusion>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- </exclusions>
2).添加以下slf4j和log4j2的依赖.
- <!-- slf4j核心包-->
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>1.7.13</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <version>1.7.13</version>
- <scope>runtime</scope>
- </dependency>
- <!--核心log4j2jar包-->
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-api</artifactId>
- <version>2.4.1</version>
- </dependency>
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-core</artifactId>
- <version>2.4.1</version>
- </dependency>
- <!--用于与slf4j保持桥接-->
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-slf4j-impl</artifactId>
- <version>2.4.1</version>
- </dependency>
- <!--web工程需要包含log4j-web,非web工程不需要-->
- <dependency>
- <groupId>org.apache.logging.log4j</groupId>
- <artifactId>log4j-web</artifactId>
- <version>2.4.1</version>
- <scope>runtime</scope>
- </dependency>
- <!--需要使用log4j2的AsyncLogger需要包含disruptor-->
- <dependency>
- <groupId>com.lmax</groupId>
- <artifactId>disruptor</artifactId>
- <version>3.2.0</version>
- </dependency>
2.web.xml中设置log4j2的监听器和过滤器(servlet3.0及以上版本不需要该步操作)
- <!--对于log4j2,Servlet2.5以前的版本需要-->
- <listener>
- <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
- </listener>
- <filter>
- <filter-name>log4jServletFilter</filter-name>
- <filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>log4jServletFilter</filter-name>
- <url-pattern>/*</url-pattern>
- <dispatcher>REQUEST</dispatcher>
- <dispatcher>FORWARD</dispatcher>
- <dispatcher>INCLUDE</dispatcher>
- <dispatcher>ERROR</dispatcher>
- </filter-mapping>
注意:log4j2不再支持properties文件了,只支持xml,json或是yaml,不指定位置的情况下默认在src/main/resources下查找。
如果需要自定义位置,需要在上面的web.xml中添加以下代码
- <context-param>
- <param-name>log4jConfiguration</param-name>
- <param-value>/WEB-INF/classes/log4j2.xml</param-value>
- </context-param>
3.log4j2.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <Configuration status="off" monitorInterval="1800">
- <properties>
- <property name="LOG_HOME">/opt/logs/hafiz/log4j2Demo/logs</property>
- <property name="ERROR_LOG_FILE_NAME">error</property>
- </properties>
- <Appenders>
- <Console name="Console" target="SYSTEM_OUT">
- <PatternLayout pattern="%d %-5p (%F:%L) - %m%n" />
- </Console>
- <RollingRandomAccessFile name="ErrorLog"
- fileName="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log"
- filePattern="${LOG_HOME}/${ERROR_LOG_FILE_NAME}.log.%d{yyyy-MM-dd}.gz">
- <PatternLayout
- pattern="%d %-5p (%F:%L) - %m%n"/>
- <Policies>
- <TimeBasedTriggeringPolicy/>
- <SizeBasedTriggeringPolicy size="100 MB"/>
- </Policies>
- <DefaultRolloverStrategy max="20"/>
- </RollingRandomAccessFile>
- </Appenders>
- <Loggers>
- <!-- 3rdparty Loggers -->
- <logger name="org.springframework.core" level="info">
- </logger>
- <logger name="org.springframework.beans" level="info">
- </logger>
- <logger name="org.springframework.context" level="info">
- </logger>
- <logger name="org.springframework.web" level="info">
- </logger>
- <logger name="com.hafiz.www.controller" level="error" includeLocation="true" additivity="false">
- <appender-ref ref="ErrorLog"/>
- <appender-ref ref="Console"/>
- </logger>
- <root level="info" includeLocation="true">
- <appender-ref ref="Console"/>
- </root>
- </Loggers>
- </Configuration>
4.测试类UserController.java
- package com.hafiz.www.controller;
- import com.hafiz.www.po.UserEntity;
- import com.hafiz.www.service.UserService;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.ResponseBody;
- import java.util.ArrayList;
- import java.util.List;
- /**
- * Desc:用户信息控制器
- * Created by hafiz.zhang on 2016/8/27.
- */
- @Controller
- @RequestMapping("/user")
- public class UserController {
- private static final Logger logger = LoggerFactory.getLogger(UserController.class);
- @Autowired
- private UserService userService;
- @RequestMapping(value = "/all", method = RequestMethod.GET)
- @ResponseBody
- public List<UserEntity> getAllUsers(){
- logger.info("[GET] /user/all getAllUsers");
- List<UserEntity> list = userService.getAllUsers();
- logger.debug("This is log of level of debug");
- logger.trace("log4j2 Demo");
- logger.error("哎呀,出错啦~");
- return list;
- }
- }
注意:在JVM启动参数中增加 -DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector 开启异步日志.
三、小问题:
项目不打印日志并且报:SLF4J: Class path contains multiple SLF4J bindings.主要问题在于在项目中既存在slf4j-log4j12的jar包又存在log4j-slf4j-impl的jar包,导致出现了两个打印日志实现类,所以slf4j门面不知道具体应该使用哪一个进行输出日志,所以导致不打印日志。
因为我之前是log4j 1.x,并且我在web.xml里面指定了log4j.properties文件的位置,第一次运行项目,忘了修改其值为log4j2.xml,出现了"Context [] startup failed due to previous errors"的错误,导致项目启动不起来,web.xml中修改为如下方式以后就正常了。
- <context-param>
- <param-name>log4jConfiguration</param-name>
- <param-value>/WEB-INF/classes/log4j2.xml</param-value>
- </context-param>
使用Slf4j集成Log4j2构建项目日志系统的完美解决方案的更多相关文章
- java项目日志系统的总结
目录 日志系统归类以及关系 日志的三个组件 slf4j的使用 项目中构建日志系统 使用例子 日志系统归类以及关系 常用的日志框架: slf4j.logback .log4j.log4j2.JUL(ja ...
- 【ELK】5.spring boot日志集成ELK,搭建日志系统
阅读前必看: ELK在docker下搭建步骤 spring boot集成es,CRUD操作完整版 ============================================== 本章集成 ...
- springboot2.7.x 集成log4j2配置写入日志到mysql自定义表格
在阅读之前请先查看[springboot集成log4j2] 本文暂不考虑抽象等实现方式,只限于展示如何自定义配置log4j2并写入mysql数据库(自定义结构) 先看下log4j2的配置 <?x ...
- 利用开源架构ELK构建分布式日志系统
问题导读 1.ELK产生的背景?2.ELK的基本组成模块以及各个模块的作用?3.ELK的使用总计有哪些? 背景 日志,对每个系统来说,都是很重要,又很容易被忽视的部分.日志里记录了程序执行的关键信息, ...
- 记一次项目上线后Log4j2不输出日志的坑
公司项目采用了Log4j2来输出日志,在开发环境和测试环境下均可以输出日志,但在生成环境就没有日志输出.开始毫无头绪,后来通过不断的排查,终于解决了这个问题.在此记录下该问题的解决过程,便于后 ...
- 6 个 K8s 日志系统建设中的典型问题,你遇到过几个?
作者 | 元乙 阿里云日志服务数据采集客户端负责人,目前采集客户端 logtail 在集团百万规模部署,每天采集上万应用数 PB 数据,经历多次双 11.双 12 考验. 导读:随着 K8s 不断 ...
- 使用 SLF4J + LogBack 构建日志系统(转)
转载自:http://www.cnblogs.com/mailingfeng/p/3499436.html 上次我们讨论了如何选择一个好的开源日志系统方案,其中的结论是:使用 SLF4J + LogB ...
- 常见java日志系统的搭配详解:关于slf4j log4j log4j2 logback jul jcl commons-logging jdk-logging
先看一张图: 是不是有点晕, 晕就对了.这个仅仅是 slf4j 的情况,实际上, 我们不仅要接触到 slf4j ,有时候还会接触其他的日志系统.且看下文分解. 1 直接使用各个日志系统 1.1 直接使 ...
- SLF4J日志系统在项目导入时频现的问题
一.概述 近期在导入一个已有的项目时,日志系统出现了一个问题.错误信息如下: SLF4J问题 SLF4J: Failed to load class "org.slf4j.impl.Stat ...
随机推荐
- CVE-2016-1240 Tomcat 服务本地提权漏洞
catalogue . 漏洞背景 . 影响范围 . 漏洞原理 . 漏洞PoC . 修复方案 1. 漏洞背景 Tomcat是个运行在Apache上的应用服务器,支持运行Servlet/JSP应用程序的容 ...
- ubuntu下载工具uget和aria2
一直想在ubuntu下找到个和迅雷差不多的下载工具.在网上找到了. 这篇文章完全是抄袭整理网上的. 我的系统版本是ubuntu14.04. 1.安装uget和aria2 sudo apt-get in ...
- HTTP Request Method共计15种
更多信息可参考http://tools.jb51.net/table/http_request_method
- Beta阶段测试报告
前端测试计划 具体测试项如下: 注册测试 登录测试 忘记密码测试 一次登录后自动登录测试 退出登录测试 编辑资料测试 查看好友测试 搜索好友测试 添加好友测试 获取当前正在游戏的房间测试 创建房间测试 ...
- 加密算法中BASE64、MD5、SHA、HMAC等之间的区别
http://blog.csdn.net/lplj717/article/details/51828692 根据项目需要了解了一下几种加密算法(参考其他博客),内容简要介绍BASE64.MD5.SHA ...
- java -- 容易放错的误区
1.按值传递 和 引用传递 (基本类型包括基本类型的包装类 或者 字符串类型 传递的是 副本 并不会改变原来的值)|| 如果是引用类型 传递的是地址,会改变原来的值. public class T ...
- Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引
因为内容比较多,所以每篇讲解一些内容,最后会放出全部代码,可以参考.操作中总会遇到各式各样的问题,个人对部分问题的研究在最后一篇 问题研究 里.欢迎大家探讨学习. 代码都经过个人测试,但仍可能有各种未 ...
- Windows下LATEX排版论文攻略—CTeX、JabRef使用介绍
Windows下LATEX排版论文攻略—CTeX.JabRef使用介绍 一.工具介绍 TeX是一个很好排版工具,在学术界十分流行,特别是数学.物理学和计算机科学界. CTeX是TeX中的一个版本,指的 ...
- System.Web.Http.Cors配置跨域访问的两种方式
System.Web.Http.Cors配置跨域访问的两种方式 使用System.Web.Http.Cors配置跨域访问,众多大神已经发布了很多文章,我就不在详细描述了,作为小白我只说一下自己的使用心 ...
- ASP.MVC时间类型json数据处理
服务端返回DateTime属性如果用自带的json方法返回的数据如下: 有2种办法解决一种是采用服务端解决方案,一种是使用前端解决方案 1.前端解决方案 第一步:对Date进行扩展 // 对Date的 ...