快速将log4j.xml 转换为 logback.xml

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 应用的日志输出频率太高,log4j同步日志输出的时候锁竞争太过激烈,导致业务线程阻塞。系统load 200+,线程数2000+ 。所以想通过切换到logback 来提升日志输出的内容。 想要切换到logback要做两件事情: * 切换pom中依赖的jar包 * 将log4j.xml 转换成 logback.xml 第一件事情比较简单,但是第二件事情稍微有些麻烦

应用的日志输出频率太高,log4j同步日志输出的时候锁竞争太过激烈,导致业务线程阻塞。系统load 200+,线程数2000+ 。所以想通过切换到logback 来提升日志输出的内容。

想要切换到logback要做两件事情:

* 切换pom中依赖的jar包
* 将log4j.xml 转换成 logback.xml 

第一件事情比较简单,但是第二件事情稍微有些麻烦,特别是碰到原本日志Appender就非常多的情况下(我们配置了超过50个Appender)一个一个手动改就很繁琐了。在网上找了很多都是从 log4j.properties 转换为 logback.xml 的,我们这边还是很少有用到log4j.properties的。 在Google 上找了好久找到了一个文章 http://rpuchkovskiy.blogspot.com/2014/11/xslt-to-convert-log4jxml-config-to.html。通过他可以把 log4j.xml 转换为 logback.xml ,不过他的实现比较老,我结合我们的使用场景稍微修改了下。

<!--
     This XLST script converts log4j.xml.bak file to logback.xml file
     trying to mimic its behavior as close as possible

     @author Roman Puchkovskiy
 -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                exclude-result-prefixes="log4j xalan"
                xmlns:log4j="http://jakarta.apache.org/log4j/"
                xmlns:xalan="http://xml.apache.org/xslt"
                xmlns:xslt="http://www.w3.org/1999/XSL/Transform">

    <xsl:output indent="yes" xalan:indent-amount="4"/>

    <xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>

    <xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

    <xsl:template match="/log4j:configuration">
        <configuration>
            <xsl:apply-templates select="appender"/>
            <xsl:apply-templates select="logger"/>
            <xsl:apply-templates select="root"/>
            <xsl:apply-templates select="comment()"/>
        </configuration>
    </xsl:template>

    <xsl:template match="appender">
        <appender>
            <xsl:attribute name="name">
                <xsl:value-of select="@name"/>
            </xsl:attribute>
            <xsl:attribute name="class">
                <xsl:choose>
                    <!-- 定义了Appender 之间的映射关系 -->
                    <xsl:when test="@class = 'org.apache.log4j.DailyRollingFileAppender'">ch.qos.logback.core.rolling.RollingFileAppender</xsl:when>
                    <xsl:when test="@class = 'com.alibaba.common.logging.spi.log4j.DailyRollingFileAppender'">ch.qos.logback.core.rolling.RollingFileAppender</xsl:when>
                    <xsl:when test="@class = 'org.apache.log4j.AsyncAppender'">ch.qos.logback.classic.AsyncAppender</xsl:when>
                    <xsl:when test="@class = 'org.apache.log4j.ConsoleAppender'">ch.qos.logback.core.ConsoleAppender</xsl:when>
                    <xsl:when test="@class = 'org.apache.log4j.net.SMTPAppender'">ch.qos.logback.classic.net.SMTPAppender</xsl:when>
                    <xsl:when test="@class = 'org.apache.log4j.net.SocketAppender'">ch.qos.logback.classic.net.SocketAppender</xsl:when>
                    <xsl:when test="@class = 'org.apache.log4j.net.SyslogAppender'">ch.qos.logback.classic.net.SyslogAppender</xsl:when>
                    <xsl:otherwise>
                        <xsl:message terminate="yes">Unknown appender class:
                            <xsl:value-of select="@class"/>
                        </xsl:message>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <xsl:apply-templates select="param"/>
            <xsl:apply-templates select="layout"/>
            <xsl:apply-templates select="filter"/>
        </appender>
        <xsl:call-template name="newline"/>
    </xsl:template>

    <xsl:template match="param">
        <xsl:choose>
            <!-- 将log4j file 转换为 logback 的file -->
            <xsl:when test="@name = 'file'">
                <xsl:element name="{concat(translate(substring(@name,1,1), $vUpper, $vLower),substring(@name, 2))}">
                    <xsl:value-of select="@value"/>
                </xsl:element>
            </xsl:when>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="layout">
        <xsl:choose>
            <!-- 将PatternLayout 做转换 -->
            <xsl:when test="@class = 'org.apache.log4j.PatternLayout'">
                <xsl:choose>
                    <xsl:when
                            test="../@class = 'org.apache.log4j.ConsoleAppender' or ../@class = 'org.apache.log4j.DailyRollingFileAppender' or ../@class = 'com.alibaba.common.logging.spi.log4j.DailyRollingFileAppender'">
                        <encoder>
                            <pattern>
                                <xsl:value-of select="param[@name = 'ConversionPattern']/@value"/>
                            </pattern>
                            <charset>UTF-8</charset>
                        </encoder>
                        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                            <xsl:element name="fileNamePattern">
                                <xsl:value-of select="../param[@name = 'file']/@value" />.%d{yyyy-MM-dd}</xsl:element>
                            <maxHistory>7</maxHistory>
                        </rollingPolicy>
                    </xsl:when>
                    <xsl:when
                            test="../@class = 'org.apache.log4j.net.SocketAppender' or ../@class = 'org.apache.log4j.net.SyslogAppender'">
                        <xsl:comment>this is NOT needed tor this logger, so it is commented out</xsl:comment>
                        <xsl:comment><![CDATA[
                            <layout>
                                <pattern>]]><xsl:value-of select="param[@name = 'ConversionPattern']/@value"/><![CDATA[</pattern>
                            </layout>]]>
                        </xsl:comment>
                    </xsl:when>
                    <xsl:otherwise>
                        <layout>
                            <pattern>
                                <xsl:value-of select="param[@name = 'ConversionPattern']/@value"/>
                            </pattern>
                        </layout>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:when>
            <xsl:otherwise>
                <xsl:message terminate="yes">Unknown layout class:
                    <xsl:value-of select="@class"/>
                </xsl:message>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="filter">
        <xsl:choose>
            <xsl:when
                    test="@class = 'org.apache.log4j.varia.LevelRangeFilter' and param[@name = 'LevelMin']/@value != '' and param[@name = 'LevelMax']/@value = 'FATAL'">
                <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                    <level>
                        <xsl:value-of select="param[@name = 'LevelMin']/@value"/>
                    </level>
                </filter>
            </xsl:when>
            <xsl:otherwise>
                <xsl:message terminate="yes">Don't know what to do with filter</xsl:message>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="logger">
        <logger>
            <xsl:attribute name="name">
                <xsl:value-of select="@name"/>
            </xsl:attribute>
            <xsl:attribute name="level">
                <xsl:choose>
                    <xsl:when test="level/@value = 'FATAL'">OFF</xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="level/@value"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <xsl:if test="@additivity != ''">
                <xsl:attribute name="additivity">
                    <xsl:value-of select="@additivity"/>
                </xsl:attribute>
            </xsl:if>
            <xsl:apply-templates select="appender-ref"/>
        </logger>
    </xsl:template>

    <xsl:template match="appender-ref">
        <appender-ref>
            <xsl:attribute name="ref">
                <xsl:value-of select="@ref"/>
            </xsl:attribute>
        </appender-ref>
    </xsl:template>

    <xsl:template match="root">
        <xsl:call-template name="newline"/>
        <root>
            <xsl:attribute name="level">
                <xsl:value-of select="level/@value"/>
            </xsl:attribute>
            <xsl:apply-templates select="appender-ref"/>
            <xsl:apply-templates select="comment()"/>
        </root>
    </xsl:template>

    <xsl:template match="comment()">
        <xsl:copy-of select="."/>
    </xsl:template>

    <xsl:template name="newline">
        <!-- don't reformat this! -->
        <xsl:text>

        </xsl:text>
    </xsl:template>

</xsl:stylesheet>

使用方式很简单:

String[] parmas = {"-IN", "log4j.xml",
                            "-XSL", "log4j-to-logback.xsl",
                            "-OUT", "logback.xml"};

org.apache.xalan.xslt.Process.Process.main(parmas);
目录
相关文章
|
XML 数据格式
日志文件logback.xml配置文件超简单(含中文注释)
这是我个人用到的logback.xml,我自己手写。
205 0
日志文件logback.xml配置文件超简单(含中文注释)
|
消息中间件 运维 Java
【Log日志】logback.xml动态配置属性值(包括接入的第三方配置)
1如何动态配置Logback的存放路径 我们在开发过程中,会使用到logback.xml 配置来管理日志文件; 比如
|
3月前
|
XML Android开发 数据格式
Eclipse 创建 XML 文件
Eclipse 创建 XML 文件
51 2
|
3月前
|
Java Maven
maven项目的pom.xml文件常用标签使用介绍
第四届人文,智慧教育与服务管理国际学术会议(HWESM 2025) 2025 4th International Conference on Humanities, Wisdom Education and Service Management
307 8
|
4月前
|
XML 前端开发 Java
讲解SSM的xml文件
本文详细介绍了SSM框架中的xml配置文件,包括springMVC.xml和applicationContext.xml,涉及组件扫描、数据源配置、事务管理、MyBatis集成以及Spring MVC的视图解析器配置。
113 1
|
4月前
|
XML JavaScript Java
java与XML文件的读写
java与XML文件的读写
51 3
|
4月前
|
XML 存储 缓存
C#使用XML文件的详解及示例
C#使用XML文件的详解及示例
198 0
|
4月前
|
XML 存储 Web App开发
查看 XML 文件
查看 XML 文件
|
5月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
95 1
|
6月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)