序:这段时间因为维护的项目存在大量日志打印,严重拖慢整体响应时间,在做性能优化的工作中对这块内容进行了升级换代,由以前的log4j升级为log4j2,以实现日志异步打印。接下来记录一下这个费时半个月的迁移踩过的坑!

相关操作步骤:

1. 在项目中移除log4j的依赖,并添加log4j2的相关依赖.(选择log4j2的版本时请留意,2.10.x之后的版本是基于java9的!如果有使用到某些特性,请考虑当前项目的jdk版本!)

<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>2.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.9.1</version>
</dependency>

我最开始使用的2.11.2版本,因为jdk原因退回到2.9.1(请注意如果你的项目是通过jenkins构建,请将api,core包的依赖直接添加进来!)  

2.修改项目中所有的报错!(这些都是jar包替换造成的!注意log4j2在实现方面与log4j是有区别的,常用的3个为:自定义appender,自定义日志等级,获取logger的方式)

自定义appender方式:

@Plugin(
name = "CustomerAppender",
category = "Core",
elementType = "appender",
printObject = true
) public final class CustomerAppender extends AbstractOutputStreamAppender<CustomerRollingFileManager> { //TODO
//此部分为自定义内容 }

  

3.本文以maven依赖管理为例,查看dependencies树,确保项目中没有其他依赖的依赖引入log4j相关jar包

这个步骤自行解决~~举例如下:

   <dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>

  

4.为步骤三中找到并移除的实现引入需要的桥接包!(此处注意大多数的项目中使用的 都是slf4j的框架,不同的版本使用Log4j2的实现需要的桥接包版本是不一样的!请仔细查看相关版本)

<!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>x.x.x</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>x.x.x</version>
</dependency>

  请根据实际需要修改对应版本,建议在maven repository中查询版本对应关系

5.根据原有log4j.xml的配置文件改造log4j2.xml(原来通过java定义的日志等级可以迁移到此处)

<CustomLevels>
<CustomLevel name="BUSI" intLevel="350" />
</CustomLevels>

  这里可以根据需要定义name,一级level,注意这个值与log4j定义的不太一样,具体请参考源码中的定义规则,我此处给的350在info等级以上

6.解决kafka日志推送问题.(log4j推送kafka一般是通过kafka-log4j-appender这个中间包去实现的,在lo4j2下需要更换推送方式,有内置的kafkaAppender,需要在依赖管理中根据需要推送的kafka服务端版本号添加对应的客户端版本号:kafka-clients)

<!--kafka日志推送-->
<Kafka name="kafkaAppender" topic="test" ignoreExceptions="true">
<PatternLayout pattern="${Console_Pattern}" />
<Property name="bootstrap.servers">x.x.x.x:端口号,x.x.x.x:端口号</Property>
<Property name="max.block.ms">2000</Property>
</Kafka>

  此处还可以设置ignoreException=false;这个时候需要去对异常做处理,可以获取异常信息.

需要添加的kafka-clients依赖如下(请修改具体版本):

<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.10.0.0</version>
</dependency>

7.解决容器问题!这个并非所有的容器都需要(至少tomcat不需要。。)目前我们服务器端使用的为jboss。在对日志升级后有可能出现对应业务日志打印到jboss的server日志中!这肯定是不允许的!解决办法:在项目的WEB-INF或者META-INF目录下添加:jboss-deployment-structure.xml文件,注意此处放置的位置和文件名都必须是这个!这是jboos规定的。此文件的作用是可以管理jboss的相关依赖,可以在此处排除它的log4j2的实包

<?xml version="1.0" encoding="UTF-8" ?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment> <exclude-subsystems>
<!-- 排除 javax.persistence.api 依赖 -->
<subsystem name="jpa" /> <!-- 排除 org.jboss.logging 依赖 -->
<subsystem name="logging" />
</exclude-subsystems> <exclusions>
<!-- 排除 org.apache.httpcomponents 依赖 -->
<module name="org.jboss.resteasy.resteasy-jaxrs" /> <!-- 排除 javax.persistence.api 依赖 -->
<module name="javaee.api" />
<module name="javax.persistence.api" />
<module name="org.hibernate" />
</exclusions> <dependencies> <!-- 排除 org.apache.httpcomponents 依赖 -->
<!-- <module name="org.apache.httpcomponents" export="true"/> --> <!-- 排除 org.jboss.logging 依赖 -->
<!-- <module name="org.jboss.logging" export="true" /> -- <!-- 排除掉jboss的 slf4j 和 log4j 实现,使用我们程序自己的包 -->
<!--<module name="org.apache.log4j" export="true" />-->
<!--<module name="org.slf4j" export="true" />-->
<module name="org.apache.commons.logging" export="true" />
<module name="org.jboss.logging.jul-to-slf4j-stub" export="true" /> </dependencies>
</deployment>
</jboss-deployment-structure>

  请根据项目实际需要做相关排除

8.解决因为包装自定义的logger导致的日志记录中不能正常记录logger打印位置的问题。(这个问题对于直接使用原生logger的项目不会有)在log4j2的api包下我们会发现没有提供可以传递FQCN的接口!所以此处我们需要直接引入core下的具体实现。在实现类中有log.logIfEnabled()方法,此方法允许传入(FQCN,level,maker,message).

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Logger; public abstract class AbstractABFrameLogger { /** 线程栈查找方法深度 */
private final static int STACK_DEEP_SIZE = 2; /** log4j把传递进来的callerFQCN在堆栈中一一比较,相等后,再往上一层即认为是用户的调用类 */
final static String FQCN = AbstractABFrameLogger.class.getName(); protected Logger log; /**
*
* @param name name
*/
public AbstractABFrameLogger(String name) {
this.log = (Logger) LogManager.getLogger(name);
} /**
* 基本debug基本,封装打印信息
* @param objLogInfo Object
*/
public void debug(Object objLogInfo) {
log.logIfEnabled(FQCN,Level.DEBUG,null,objLogInfo);
} }

  

完成上述步骤后,整个log4j的升级工作也就差不多做完啦~恭喜

log4j到log4j2升级迁移方案的更多相关文章

  1. Slf4j与log4j及log4j2的关系及使用方法

    Slf4j与log4j及log4j2的关系及使用方法 slf4j slf4j仅仅是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就比如JDBC一样,只是一种规则而已,所以单独 ...

  2. Slf4j与log4j及log4j2、logbak的关系及使用方法

    Slf4j与log4j及log4j2的关系及使用方法 slf4j slf4j仅仅是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就比如JDBC一样,只是一种规则而已,所以单独 ...

  3. Ceph 集群整体迁移方案(转)

    场景介绍:在我们的IDC中,存在着运行了3-6年的Ceph集群的服务器,这些服务器性能和容量等都已经无法满足当前业务的需求,在购入一批高性能机器后,希望将旧机器上的集群整体迁移到新机器上,当然,是保证 ...

  4. 蚂蚁金服 Service Mesh 渐进式迁移方案|Service Mesh Meetup 实录

    小蚂蚁说: 本文是基于在 Service Mesher Meetup 上海站的主题分享<蚂蚁金服 Service Mesh 渐进式迁移方案>内容整理,完整的分享 PPT 获取方式见文章底部 ...

  5. Java logger组件:slf4j, jcl, jul, log4j, logback, log4j2

    先说结论 建议优先使用logback 或 log4j2.log4j2 不建议和 slf4j 配合使用,因为格式转换会浪费性能. 名词:jcl 和 jul 标题中的 jcl 是 apache Jakar ...

  6. 转:Java logger组件:slf4j, jcl, jul, log4j, logback, log4j2

    先说结论 建议优先使用logback 或 log4j2.log4j2 不建议和 slf4j 配合使用,因为格式转换会浪费性能. 名词:jcl 和 jul 标题中的 jcl 是 apache Jakar ...

  7. JCL、SLF4J、Log4J、Log4J2、LogBack和JUL之间的关系,你搞清楚了吗?

    写在前面 日志组件是我们平时开发过程中必然会用到的组件.在系统中正确的打印日志至少有下面的这些好处: 调试:在程序的开发过程中,必然需要我们不断的调试以达到程序能正确执行的状态 .记录日志可以让开发人 ...

  8. 一文讲尽门面日志slf4j和log4j、log4j2、logback依赖jar引用关系

    公众号Mac代码分割阅读链接 前言 之前都是使用SparkStreaming开发,最近打算学习一下Flink,就从官网下载了Flink 1.11,打算搞一个客户端,将程序提交在yarn上.因为Flin ...

  9. 不同场景下 MySQL 的迁移方案

    一 目录 一 目录 二 为什么要迁移 三 MySQL 迁移方案概览 四 MySQL 迁移实战 4.1 场景一 一主一从结构迁移从库 4.2 场景二 一主一从结构迁移指定库 4.3 场景三 一主一从结构 ...

随机推荐

  1. XPath和CssSelector定位总结

    1. 介绍XPath和CssSelector 2. XPath有哪些方式 2.1 通过XPath语法 2.2 Contains关键字 2.3 Start-With 2.4 Or和And关键字 2.5 ...

  2. java并发多线程显式锁Condition条件简介分析与监视器 多线程下篇(四)

    Lock接口提供了方法Condition newCondition();用于获取对应锁的条件,可以在这个条件对象上调用监视器方法 可以理解为,原本借助于synchronized关键字以及锁对象,配备了 ...

  3. cocos creator主程入门教程(七)—— MVC架构

    五邑隐侠,本名关健昌,10年游戏生涯,现隐居五邑.本系列文章以TypeScript为介绍语言. 这一篇将介绍在游戏客户端常用的架构MVC架构.一个游戏的MVC如下划分: M:1)单例全局的数据中心Wo ...

  4. Python3+Selenium2完整的自动化测试实现之旅(一):自动化测试环境搭建

    1     环境搭建准备 (1)    下载Python3版本的安装包,直接官网下载即可:Python官网:https://www.python.org/ (2)    下载Python的基础工具包p ...

  5. AspNetCore+Swagger 生成Model 描述

    AspNetCore+Swagger 生成Model 描述 前言: 本篇文章实现是基于上一篇文章,进下补充:多余的就不多说了,只是为了实现Model的描述生成:有兴趣的可以结合上一篇的进行实现:如有更 ...

  6. DSAPI 简单WebAPI实现

    使用DSAPI实现一个简单的WebAPI功能,以便各客户端访问.支持身份验证,支持基础防护. 新建项目(以下演示控制台示例),引用DSAPI.dll. 复制粘贴以下代码: Module Module1 ...

  7. oracle学习笔记(三) DCL 数据控制语言与 DDL 数据定义语言

    DCL 数据控制语言 Data control language 之前说过的授权和收权利语句 grant, revoke DDL 数据定义语言 Data define language create ...

  8. 学习笔记—JDBC

    JDBC的概念 JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言 ...

  9. vue的组件化运用(数据在两个组件互传,小问题总结)

    一.vue的组件化应用 首先,知道有哪些相关的属性需要用到,再慢慢去理解,运用. 1.两个vue页面 2. slot占位符(可用可不用) 3.props内置属性 4.watch监听函数 5.impor ...

  10. PM领导能力成熟度2级

    人生如戏,大幕拉开,他走上舞台,饰演PM一角. 从技术岗位迈向管理岗位的第一步,对大多数像他一样的新晋PM来说,并不轻松.技术知识与经验是他曾经的主要才能与成功基础,而从成熟度一级开始,身为管理者的他 ...