Java猿社区之日志组件升级Log4j2

@[toc]

前言

升级前提介绍:在线客服关于升级Log4j2记录日志的总结

本次升级样例项目:

  • ddky-backManage-all
  • ddky-report-web

参考:
http://logging.apache.org/log4j/2.x/manual/webapp.html#Servlet-2.5

升级web

修改pom

删除旧依赖

  • 此处需要删除各包下引用的低版本log4j,使用excludes去除
  • 可以使用mvn dependency:tree查看冲突和低版本log4j引用情况
  • idea可以直接使用Digrams -> show dependencies
                <!-- Log4j 删除旧版本 -->
        <!--<dependency>-->
            <!--<groupId>org.slf4j</groupId>-->
            <!--<artifactId>slf4j-api</artifactId>-->
            <!--<version>${slf4j.version}</version>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>org.slf4j</groupId>-->
            <!--<artifactId>slf4j-log4j12</artifactId>-->
            <!--<version>${slf4j.version}</version>-->
        <!--</dependency>-->
        <!--<dependency>-->
            <!--<groupId>log4j</groupId>-->
            <!--<artifactId>log4j</artifactId>-->
            <!--<version>${log4j.version}</version>-->
        <!--</dependency>-->
        
        <!-- 排除log4j和logback依赖包 -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.6</version>
            <exclusions>
                <!--  排除log4j1的方式  -->
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
                <!--  排除logback的方式  -->
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <!-- 去除disconfig log4j1 -->
        <dependency>
            <groupId>com.baidu.disconf</groupId>
            <artifactId>disconf-client</artifactId>
            <version>2.6.35-ddky</version>
            <exclusions>
                <exclusion>
                     <groupId>commons-io</groupId>
                     <artifactId>commons-io</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
            <exclusions>
                <!--  排除log4j1的方式  -->
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
                <!--  排除logback的方式  -->
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        ...等等等

引入log4j2依赖:
版本统一使用:

  • log4j-2.11.2
  • disruptor-3.4.2

<!-- ***********Log4j2升级开始********** -->

        <!-- log4j2依赖包 异步日志 -->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>3.4.2</version>
        </dependency>

        <!-- slf4j门面包 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>

        <!-- log4j2核心包 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.11.2</version>
        </dependency>

        <!-- log4j2门面包 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.11.2</version>
        </dependency>

        <!-- 该包是 log4j 升级到 log4j2的必须包 使用该包 不需要修改以前的 Logger.getLogger()这种获取对象的方式 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-1.2-api</artifactId>
            <version>2.11.2</version>
        </dependency>
        <!-- 该包是slf4j 升级到 log4j2的必须包 使用该包 其他依赖jar中依赖slf4j 不会报错 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.11.2</version>
        </dependency>

        <!-- web项目需要引用此包 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-web</artifactId>
            <version>2.11.2</version>
        </dependency>

        <!-- 桥接:告诉commons logging使用Log4j2 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-jcl</artifactId>
            <version>2.11.2</version>
            <scope>runtime</scope>
        </dependency>

        <!-- ***********Log4j2升级结束********** -->

配置web.xml

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mMkdrvJ3-1578400083971)(./1578389815402.png)]
升级web-app到2.5版本(推荐,由于公司项目servlet都采用2.5版本)

原先:

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

改为:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

修改原先的配置

        <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener
        </listener-class>
    </listener>
        <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.properties</param-value>
    </context-param>

添加新配置:

    <!--日志升级开始-->
    <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>
        <!-- Servlet 3.0 w/ disabled auto-initialization only; not supported in 2.5 -->
        <!-- <dispatcher>ASYNC</dispatcher> -->
    </filter-mapping>

    <context-param>
        <param-name>log4jConfiguration</param-name>
        <param-value>/WEB-INF/classes/log4j2.xml</param-value>
        <!--<param-value>classpath:log4j2.xml</param-value>-->
    </context-param>
    <!--<context-param>-->
        <!--<param-name>log4jRefreshInterval</param-name>-->
        <!--<param-value>1000</param-value>-->
    <!--</context-param>-->
    <!--日志升级结束-->
升级web-app到3.0版本(不推荐,升级改动范围大)

原先:

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

改为:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

添加新配置:

    <!--日志升级开始-->
    <context-param>
        <param-name>log4jConfiguration</param-name>
        <param-value>/WEB-INF/classes/log4j2.xml</param-value>
        <!--<param-value>classpath:log4j2.xml</param-value>-->
    </context-param>
    <context-param>
        <param-name>isLog4jAutoInitializationDisabled</param-name>
        <param-value>true</param-value>
    </context-param>
    <!--日志升级结束-->

升级pom依赖servlet-api版本到3.0

创建resources/log4j2.xml

并备份和删除原先的log4j.properties

创建log4j2.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="30" strict="true">

    <Properties>
        <!-- 日志输出级别 -->
        <Property name="LOG_DEBUG_LEVEL" value="debug"/>
        <Property name="LOG_INFO_LEVEL" value="info"/>
        <Property name="LOG_WARN_LEVEL" value="warn"/>
        <!-- error级别日志 -->
        <Property name="LOG_ERROR_LEVEL" value="error"/>
        <!-- 在当前目录下创建名为log目录做日志存放的目录 -->
        <!--<Property name="LOG_HOME" value="./log"/>-->
        <Property name="LOG_HOME" value="E:\dd\codes\o2o\20160219\web\ddky_report_web\log"/>
        <!-- 档案日志存放目录 -->
        <Property name="LOG_ARCHIVE" value="${LOG_HOME}/archive"/>
        <!-- 模块名称, 影响日志配置名,日志文件名,根据自己项目进行配置 -->
        <Property name="LOG_MODULE_NAME" value="ddky-report-web"/>
        <!-- 日志文件大小,超过这个大小将被压缩 -->
        <Property name="LOG_MAX_SIZE" value="100 MB"/>
        <!-- 保留多少天以内的日志 -->
        <Property name="LOG_DAYS" value="30"/>
        <!--输出日志的格式:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度, %msg:日志消息,%n是换行符 -->
        <Property name="LOG_PATTERN" value="%d [%t] %-5level %logger{0} - %msg%n"/>
        <!--interval属性用来指定多久滚动一次-->
        <Property name="TIME_BASED_INTERVAL" value="1"/>
    </Properties>

    <Appenders>
        <!-- 控制台输出 -->
        <Console name="STDOUT" target="SYSTEM_OUT">
            <!--输出日志的格式-->
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="${LOG_DEBUG_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
        </Console>

        <!--只记录debug级别以上的日志,与info级别的日志分不同的文件保存-->
        <RollingRandomAccessFile name="RollingRandomAccessFileDebug"
                                 fileName="${LOG_HOME}/debug.log"
                                 filePattern="${LOG_ARCHIVE}/debug-%d{yyyy-MM-dd}-%i.log.gz"
                                 immediateFlush="true">
            <Filters>
                <ThresholdFilter level="${LOG_DEBUG_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="${LOG_DAYS}"/>
        </RollingRandomAccessFile>

        <!-- 这个会打印出所有的info级别以上,error级别一下的日志,每次大小超过size或者满足TimeBasedTriggeringPolicy,则日志会自动存入按年月日建立的文件夹下面并进行压缩,作为存档-->
        <!--异步日志会自动批量刷新,所以将immediateFlush属性设置为false-->
        <RollingRandomAccessFile name="RollingRandomAccessFileInfo"
                                 fileName="${LOG_HOME}/info.log"
                                 filePattern="${LOG_ARCHIVE}/info-%d{yyyy-MM-dd}-%i.log.gz"
                                 immediateFlush="false">
            <Filters>
                <!--如果是error级别拒绝,设置 onMismatch="NEUTRAL" 可以让日志经过后续的过滤器-->
                <ThresholdFilter level="${LOG_ERROR_LEVEL}" onMatch="DENY" onMismatch="NEUTRAL"/>
                <!--如果是info\warn输出-->
                <ThresholdFilter level="${LOG_INFO_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,根据当前filePattern设置是1天滚动一次-->
                <TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认同一文件夹下最多保存7个文件-->
            <DefaultRolloverStrategy max="${LOG_DAYS}"/>
        </RollingRandomAccessFile>

        <!--只记录error级别以上的日志,与info级别的日志分不同的文件保存-->
        <RollingRandomAccessFile name="RollingRandomAccessFileError"
                                 fileName="${LOG_HOME}/error.log"
                                 filePattern="${LOG_ARCHIVE}/error-%d{yyyy-MM-dd}-%i.log.gz"
                                 immediateFlush="false">
            <Filters>
                <ThresholdFilter level="${LOG_ERROR_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="${LOG_DAYS}"/>
        </RollingRandomAccessFile>

        <!--只记录warn级别以上的日志,与info级别的日志分不同的文件保存-->
        <RollingRandomAccessFile name="RollingRandomAccessFileWarn"
                                 fileName="${LOG_HOME}/warn.log"
                                 filePattern="${LOG_ARCHIVE}/warn-%d{yyyy-MM-dd}-%i.log.gz"
                                 immediateFlush="false">
            <Filters>
                <ThresholdFilter level="${LOG_WARN_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="${LOG_DAYS}"/>
        </RollingRandomAccessFile>

    </Appenders>

    <Loggers>

        <!-- 本机环境使用 -->
        <!--<Root level="${LOG_DEBUG_LEVEL}">-->
            <!--<AppenderRef ref="STDOUT"/>-->
            <!--<AppenderRef ref="RollingRandomAccessFileInfo"/>-->
            <!--<AppenderRef ref="RollingRandomAccessFileError"/>-->
            <!--<AppenderRef ref="RollingRandomAccessFileDebug"/>-->
            <!--<AppenderRef ref="RollingRandomAccessFileWarn"/>-->
        <!--</Root>-->

        <!-- 开发环境使用 -->
        <Root level="${LOG_INFO_LEVEL}">
            <AppenderRef ref="STDOUT"/>
            <AppenderRef ref="RollingRandomAccessFileInfo"/>
            <AppenderRef ref="RollingRandomAccessFileError"/>
            <AppenderRef ref="RollingRandomAccessFileWarn"/>
        </Root>

        <!-- 生产预发布环境使用 -->
        <!--<Root level="${LOG_INFO_LEVEL}" includeLocation="false">-->
        <!--<AppenderRef ref="RollingRandomAccessFileInfo"/>-->
        <!--<AppenderRef ref="RollingRandomAccessFileError"/>-->
        <!--</Root>-->


        <!-- 第三方日志系统 -->
        <logger name="org.springframework.core" level="info" />
        <logger name="org.springframework.beans" level="info" />
        <logger name="org.springframework.context" level="info" />
        <logger name="org.springframework.web" level="info" />
        <logger name="org.jboss.netty" level="warn" />
        <logger name="org.apache.http" level="warn" />

    </Loggers>

</Configuration>

修改log4j2.xml中属性

  • immediateFlush:如果使用异步日志,请设置为false,同步日志,请设置为true
  • LOG_MODULE_NAME:模块名称,建议按照项目模块命名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zItlk7Om-1578400083972)(./1578389836501.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JAsazHkm-1578400083973)(./1578389844163.png)]

配置log4j2.component.properties

# 设置异步日志系统属性
log4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
AsyncLoggerConfig.WaitStrategy=Sleep
#AsyncLoggerConfig.RingBufferSize=10240

Service服务

打印druid sql—修改applicationContext.xml

添加如下配置:

    <!-- druid 打印sql日志 -->
    <bean id="log-filter" class="com.alibaba.druid.filter.logging.Slf4jLogFilter">
        <property name="connectionLogEnabled" value="false"/>
        <property name="statementLogEnabled" value="false"/>
        <property name="resultSetLogEnabled" value="true"/>
        <property name="statementExecutableSqlLogEnable" value="true"/>
    </bean>

引入log-filter

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u376jDrk-1578400083973)(./1578389861224.png)]

log4j2.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" monitorInterval="30" strict="true">

    <Properties>
        <!-- 日志输出级别 -->
        <Property name="LOG_DEBUG_LEVEL" value="debug"/>
        <Property name="LOG_INFO_LEVEL" value="info"/>
        <Property name="LOG_WARN_LEVEL" value="warn"/>
        <!-- error级别日志 -->
        <Property name="LOG_ERROR_LEVEL" value="error"/>
        <!-- 在当前目录下创建名为log目录做日志存放的目录 -->
        <Property name="LOG_HOME" value="./log"/>
        <!--<Property name="LOG_HOME" value="E:\dd\codes\log"/>-->
        <!--<Property name="LOG_HOME" value="E:\dd\codes\o2o\20160219\web\ddky_report_web\log"/>-->
        <!-- 档案日志存放目录 -->
        <Property name="LOG_ARCHIVE" value="${LOG_HOME}/archive"/>
        <!-- 模块名称, 影响日志配置名,日志文件名,根据自己项目进行配置 -->
        <Property name="LOG_MODULE_NAME" value="ddky-backManage-all"/>
        <!-- 日志文件大小,超过这个大小将被压缩 -->
        <Property name="LOG_MAX_SIZE" value="100 MB"/>
        <!-- 保留多少天以内的日志 -->
        <Property name="LOG_DAYS" value="30"/>
        <!--输出日志的格式:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度, %msg:日志消息,%n是换行符 -->
        <Property name="LOG_PATTERN" value="%d [%t] %-5level %logger{0} - %msg%n"/>
        <!--interval属性用来指定多久滚动一次-->
        <Property name="TIME_BASED_INTERVAL" value="1"/>
    </Properties>

    <Appenders>
        <!-- 控制台输出 -->
        <Console name="STDOUT" target="SYSTEM_OUT">
            <!--输出日志的格式-->
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="${LOG_DEBUG_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
        </Console>

        <!--只记录debug级别以上的日志,与info级别的日志分不同的文件保存-->
        <RollingRandomAccessFile name="RollingRandomAccessFileDebug"
                                 fileName="${LOG_HOME}/debug.log"
                                 filePattern="${LOG_ARCHIVE}/debug-%d{yyyy-MM-dd}-%i.log.gz"
                                 immediateFlush="true">
            <Filters>
                <ThresholdFilter level="${LOG_DEBUG_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="${LOG_DAYS}"/>
        </RollingRandomAccessFile>

        <!-- 这个会打印出所有的info级别以上,error级别一下的日志,每次大小超过size或者满足TimeBasedTriggeringPolicy,则日志会自动存入按年月日建立的文件夹下面并进行压缩,作为存档-->
        <!--异步日志会自动批量刷新,所以将immediateFlush属性设置为false-->
        <RollingRandomAccessFile name="RollingRandomAccessFileInfo"
                                 fileName="${LOG_HOME}/info.log"
                                 filePattern="${LOG_ARCHIVE}/info-%d{yyyy-MM-dd}-%i.log.gz"
                                 immediateFlush="true">
            <Filters>
                <!--如果是error级别拒绝,设置 onMismatch="NEUTRAL" 可以让日志经过后续的过滤器-->
                <ThresholdFilter level="${LOG_ERROR_LEVEL}" onMatch="DENY" onMismatch="NEUTRAL"/>
                <!--如果是info\warn输出-->
                <ThresholdFilter level="${LOG_INFO_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!--interval属性用来指定多久滚动一次,根据当前filePattern设置是1天滚动一次-->
                <TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认同一文件夹下最多保存7个文件-->
            <DefaultRolloverStrategy max="${LOG_DAYS}"/>
        </RollingRandomAccessFile>

        <!--只记录error级别以上的日志,与info级别的日志分不同的文件保存-->
        <RollingRandomAccessFile name="RollingRandomAccessFileError"
                                 fileName="${LOG_HOME}/error.log"
                                 filePattern="${LOG_ARCHIVE}/error-%d{yyyy-MM-dd}-%i.log.gz"
                                 immediateFlush="true">
            <Filters>
                <ThresholdFilter level="${LOG_ERROR_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="${LOG_DAYS}"/>
        </RollingRandomAccessFile>

        <!--只记录warn级别以上的日志,与info级别的日志分不同的文件保存-->
        <RollingRandomAccessFile name="RollingRandomAccessFileWarn"
                                 fileName="${LOG_HOME}/warn.log"
                                 filePattern="${LOG_ARCHIVE}/warn-%d{yyyy-MM-dd}-%i.log.gz"
                                 immediateFlush="true">
            <Filters>
                <ThresholdFilter level="${LOG_WARN_LEVEL}" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="${LOG_DAYS}"/>
        </RollingRandomAccessFile>

        <!--druid的日志记录追加器-->
        <RollingRandomAccessFile name="druidSqlRollingFile" fileName="${LOG_HOME}/druid-sql.log"
                                 filePattern="${LOG_ARCHIVE}/druid-sql-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="${TIME_BASED_INTERVAL}"/>
                <SizeBasedTriggeringPolicy size="${LOG_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="${LOG_DAYS}"/>
        </RollingRandomAccessFile>

    </Appenders>

    <Loggers>

        <!-- 本机环境使用 -->
        <!--<Root level="${LOG_DEBUG_LEVEL}" includeLocation="true" additivity="true">-->
        <!--<AppenderRef ref="STDOUT"/>-->
        <!--<AppenderRef ref="RollingRandomAccessFileInfo"/>-->
        <!--<AppenderRef ref="RollingRandomAccessFileError"/>-->
        <!--<AppenderRef ref="RollingRandomAccessFileDebug"/>-->
        <!--<AppenderRef ref="RollingRandomAccessFileWarn"/>-->
        <!--</Root>-->

        <!-- 开发环境使用 -->
        <Root level="${LOG_INFO_LEVEL}" includeLocation="true" additivity="true">
            <AppenderRef ref="STDOUT"/>
            <AppenderRef ref="RollingRandomAccessFileInfo"/>
            <AppenderRef ref="RollingRandomAccessFileError"/>
            <AppenderRef ref="RollingRandomAccessFileWarn"/>
        </Root>

        <!--记录druid-sql的记录-->
        <logger name="druid.sql.Statement" level="debug" additivity="false">
        <appender-ref ref="druidSqlRollingFile"/>
        </logger>

        <!-- 生产预发布环境使用 -->
        <!--<Root level="${LOG_INFO_LEVEL}" includeLocation="false" additivity="false">-->
        <!--<AppenderRef ref="RollingRandomAccessFileInfo"/>-->
        <!--<AppenderRef ref="RollingRandomAccessFileError"/>-->
        <!--</Root>-->


        <!-- 第三方日志系统 -->
        <logger name="org.springframework.core" level="info" />
        <logger name="org.springframework.beans" level="info" />
        <logger name="org.springframework.context" level="info" />
        <logger name="org.springframework.web" level="info" />
        <logger name="org.jboss.netty" level="warn" />
        <logger name="org.apache.http" level="warn" />
        <Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
        <Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
        <Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
        <logger name="org.apache.sshd.common.util.SecurityUtils" level="warn"/>
        <Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
        <Logger name="org.crsh.plugin" level="warn" />
        <logger name="org.crsh.ssh" level="warn"/>
        <Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
        <Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
        <logger name="org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration" level="warn"/>
        <logger name="org.springframework.boot.actuate.endpoint.jmx" level="warn"/>
        <logger name="org.thymeleaf" level="warn"/>

    </Loggers>

</Configuration>

配置log4j2.component.properties

# 设置异步日志系统属性
log4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
AsyncLoggerConfig.WaitStrategy=Sleep
#AsyncLoggerConfig.RingBufferSize=10240

开关异步日志

通过修改log4j2.component.properties属性
当需要开启异步日志时:

# 设置异步日志系统属性
log4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
AsyncLoggerConfig.WaitStrategy=Sleep

当需要关闭异步日志,开启同步日志时:(直接注释配置即可)

# 设置异步日志系统属性
#log4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
#AsyncLoggerConfig.WaitStrategy=Sleep

如何使用

@Slf4j 或 @Log4j2注解 和 手动创建Logger

  • 通过引入lombok包, 直接在类上引用@Slf4j 或 @Log4j2注解
  • 通过手动创建Logger类(slf4j或者log4j2)
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>

测试示例:

package com.ddky;

import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
//import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.CountDownLatch;

/**
 * @program: 20160219
 * @description:
 * @author: zhouzhixiang
 * @date: 2020-01-06
 * @company: 叮当快药科技集团有限公司
 **/
//@Slf4j
@Log4j2
public class Log4j2Test {

    // 使用slf4j
    private static final Logger log = LoggerFactory.getLogger(Log4j2Test.class);
    private int totalThread = 50;
    // 使用log4j2
//    private static final Logger log = LogManager.getLogger(Log4j2Test.class);

    @Test
    public void testLog() {
        log.info("Test*******************************************");
        log.error("Test*******************************************");
        log.warn("Test*******************************************");
        log.debug("Test*******************************************");
    }

//    @Test
    public void fixedPringting() throws InterruptedException {
        log.info("log4j2 100万 start printing");
        final CountDownLatch cdl = new CountDownLatch(totalThread);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < totalThread; i++) {
            new Thread(() -> {
                for (int j = 0; j < 200000; j++) {
                    log.info("log4j2 performance test " +j);
                }
            }).start();
                    cdl.countDown();
        }
        cdl.await();
        long endTime = System.currentTimeMillis();
        log.info("log4j2 100万 end cost time "+ (endTime - startTime));
    }

    public static void main(String[] args) throws InterruptedException {
        log.info("log4j2 1000万 start printing");
        Integer totalThread = 50;
        final CountDownLatch cdl = new CountDownLatch(totalThread);
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < totalThread; i++) {
            new Thread(() -> {
                for (int j = 0; j < 2000; j++) {
                    log.info("log4j2 performance test "+ j);
                }
                cdl.countDown();
            }).start();
        }
        cdl.await();
        long endTime = System.currentTimeMillis();
        log.error("log4j2 1000万 end cost time = "+ (endTime - startTime));
    }

    @Test
    public void isAsyncLog() {
        log.info("是否为异步日志1:"+ AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志2:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志3:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志4:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志5:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志6:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志7:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志8:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志9:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志10:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志11:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志11:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志11:"+AsyncLoggerContextSelector.isSelected());
        log.info("是否为异步日志11:"+AsyncLoggerContextSelector.isSelected());
    }

    @Test
    public void testFori() {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                isAsyncLog();
            }).start();
            log.info(String.valueOf(i));
//            log.error(String.valueOf(i));
//            log.debug(String.valueOf(i));
//            log.warn(String.valueOf(i));
        }
    }
}

注意事项

  • 对于需要审计操作的日志,请开启同步日志,不建议开启异步日志。
  • 引入jar依赖注意版本统一管理(以上引入未作版本管理,仅作参考)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容