SpringBoot Log4j2 日志学习

简介

Java 中比较常用的日志工具类,有:

  • Log4j、
  • SLF4j、
  • Commons-logging(简称jcl)、
  • Logback、
  • Log4j2(Log4j 升级版)、
  • Jdk Logging

Spring Boot 默认使用 Logback,但相比较而言,Log4j2 在性能上面会更好。spring-boot高版本都不再支持log4j,而是支持log4j2

log4j.xml 示例

<?xml version="1.0" encoding="UTF-8"?>
<!--
    status : 这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,会看到log4j2内部各种详细输出
    指的是如果 Log4j2 本身出错,打印出的日志级别配置

    monitorInterval : Log4j 能够自动检测修改配置文件和重新配置本身
    设置间隔秒数。此处表示每隔30秒重读一次配置文件
-->

<!--TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF-->
<Configuration status="OFF" monitorInterval="30">

    <!-- 定义一些变量值,可供下面配置使用,例如日志存储目录等 -->
    <Properties>
        <Property name="App">mybatis-demo</Property>
        <Property name="LogDir">logs</Property>
        <Property name="SplitSize">10 MB</Property>
    </Properties>

    <!-- 定义所有的appender -->
    <!-- Appenders标签,其实就是输出,有各种扩展组件 -->
    <Appenders>

        <!-- 输出控制台日志的配置 -->
        <!-- ConsoleAppender   输出结果到控制台 -->
        <Console name="Console" target="SYSTEM_OUT">
            <!-- ThresholdFilter :过滤器 -->
            <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 输出日志的格式 -->
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} %L %M - %msg%xEx%n"/>
        </Console>

        <!-- 存储所有error信息 -->
        <!-- FileAppender  输出结果到指定文件 -->
        <!-- append:是否追加,true表示追加内容到所在的日志,false表示每次都覆盖 -->
        <File name="WarnLog" fileName="${LogDir}/${App}-warn.log" append="false">
            <!-- 添加过滤器ThresholdFilter,可以有选择的输出某个级别以上的类别 onMatch="ACCEPT" onMismatch="DENY"意思是匹配就接受,否则直接拒绝  -->
            <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %L %M - %msg%xEx%n"/>
        </File>

        <!-- 文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,-->
        <!-- 这个也挺有用的,适合临时测试用 -->
        <!-- 这个appender的好处是有一个append为false的属性,这样,每次运行都会清空上次的日志,这样就不会因为一直在调试而增加这个文件的内容,查起来也方便,这个和输出到控制台就一个效果了 -->
        <File name="log" fileName="${LogDir}/test.log" append="false">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M -
                    %msg%xEx%n"/>
        </File>

        <!-- Rolling File Appender -->
        <!-- 打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
        <!-- RollingFileAppender   同样输出结果到文件,区别是用一个buffer,因此速度会快点 -->
        <!-- filePattern:表示当日志到达指定的大小或者时间,产生新日志时,旧日志的命名路径 -->
        <RollingFile name="InfoLog" fileName="${LogDir}/${App}-info.log" immediateFlush="true" filePattern="${LogDir}/$${date:yyyy-MM}/${App}-info-%d{MM-dd-yyyy}.log" append="false">
            <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} [%t] %-5level %logger{36} %L %M - %msg%xEx%n"/>
            <SizeBasedTriggeringPolicy size="${SplitSize}"/>
            <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            <!-- 指定每天的最大压缩包个数,默认7个,超过了会覆盖之前的 -->
            <DefaultRolloverStrategy max="50"/>
        </RollingFile>

        <!-- RollingRandomAccessFile 即表示以文件方式记录 -->
        <!-- filePattern的设置,它与24行的SizeBasedTriggeringPolicy(表示单个文件最大多少容量)结合在一起,非常有用,
        以这段配置为例,当单个文件达到10M后,会自动将以前的内容,先创建类似 2014-09(年-月)的目录,然后按 "xxx-年-月-日-序号"命名,打成压缩包。DefaultRolloverStrategy max="50"表示压缩包,最多保留50个 -->
        <RollingRandomAccessFile name="ErrorLog" fileName="${LogDir}/${App}-error.log" immediateFlush="true" filePattern="${LogDir}/error-%d{yyyy-MM-dd}.log" append="false">
            <PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} [%t] %-5level %logger{36} %L %M - %msg%xEx%n"/>
            <Policies>
                <!-- 每天生成一个日志文件 -->
                <!-- TimeBasedTriggeringPolicy 基于时间的触发策略。该策略主要是完成周期性的log文件封存工作。有两个参数:
                interval,integer型,指定两次封存动作之间的时间间隔。
                单位:以日志的命名精度来确定单位,比如yyyy-MM-dd-HH 单位为小时,yyyy-MM-dd-HH-mm 单位为分钟 -->
                <!-- 关键点在于 filePattern后的日期格式,以及TimeBasedTriggeringPolicy的interval,日期格式精确到哪一位,interval也精确到哪一个单位  -->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!-- 每到 10M 生成一个日志文件 -->
                <SizeBasedTriggeringPolicy size="${SplitSize}"/>
            </Policies>
            <Filters>
                <!-- 只记录error级别信息 -->
                <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <!-- 最大保存文件数,超过了会覆盖之前的 -->
            <DefaultRolloverStrategy max="50"/>
        </RollingRandomAccessFile>
    </Appenders>

    <!--定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <!-- loggers标签,用于定义logger的level和所采用的appender,其中appender-ref必须为先前定义的appenders的名称 -->
    <Loggers>
        <!-- 用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。 -->
        <!--第三方的软件日志级别 -->
        <!-- additivity="true"这里注意一下,改成false,root logger就不会再起作用,即只会记录在文件里,控制台无输出 -->
        <logger name="org.springframework" level="INFO" additivity="true">
            <AppenderRef ref="InfoLog"/>
        </logger>

        <!-- 关于logger的命名,很有讲究的 -->
        <!-- 如果你的logger中也有日志级别的配置,如果级别都在error以上,你的appender里面也就不会输出erro以下的信息了 -->
        <Logger name="org.apache" level="ERROR" additivity="true">
            <AppenderRef ref="ErrorLog"/>
        </Logger>

        <!-- root logger 配置,全局配置,默认所有的Logger都继承此配置 -->
        <!-- All < Trace < Debug < Info < Warn < Error < Fatal < OFF. -->
        <!-- 为log的默认输出形式,如果一个类的log没有在loggers中明确指定其输出level与格式,那么就会采用root中定义的格式 -->
        <Root level="ERROR" additivity="true">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="InfoLog"/>
            <AppenderRef ref="WarnLog"/>
            <AppenderRef ref="ErrorLog"/>
        </Root>
    </Loggers>

</Configuration>

Github 配置地址:SpringBoot-Note/mybatis-demo/src/main/resources/log4j2.xml

实验

    <Loggers>
        <logger name="org.springframework" level="INFO" additivity="true">
            <AppenderRef ref="ErrorLog"/>
        </logger>

        <Root level="info" additivity="true">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="InfoLog"/>
            <AppenderRef ref="WarnLog"/>
            <AppenderRef ref="ErrorLog"/>
        </Root>
    </Loggers>
  • 注释了 Root 中对 InfoLog 的引用,org.springframework Logger 等级为 OFF 时,info.log 文件无内容;
  • 注释了 Root 中对 InfoLog 的引用,org.springframework Logger 等级为 iNFO 时,info.log 文件则会有 org.springframework 包的相关日志内容;
<logger name="org.springframework" level="INFO" additivity="true">
    <AppenderRef ref="InfoLog"/>
</logger>

<Root level="ERROR" additivity="true">
    <AppenderRef ref="Console"/>
    <AppenderRef ref="InfoLog"/>
    <AppenderRef ref="WarnLog"/>
    <AppenderRef ref="ErrorLog"/>
</Root>
  • ROOT 等级设为 ERROR 时,org.springframework Logger 等级设为 OFF 时,发现原来的 warn.loginfo.log 文件中,都只有级别大于或等于 ERROR 的日志信息了;
  • ROOT 等级设为 ERROR 时,org.springframework Logger 等级设为 INFO 时,发现info.log 文件中,增加了 org.springframework 包的相关 INFO 级别的日志信息了;

总结

  • Logger 日志等级和 appender 日志等级的关系:logger 日志等级和 appender 日志登记,谁「高」听谁的;
  • 普通 Logger 的优先级高

注意点

1.多个 appender 不能指向同一个日志文件,否则会报错:Configuration has multiple incompatible Appenders pointing to the same resource 'logs/mybatis-demo-warn.log'
2.Root Logger 只能有一个,普通的 Logger 可以定义多个,可以细致到给某个类定义;
3.我们使用 FileAppender 的时候,我们配置是 ImmediateFlush=true,一旦有新日志写入,立马将日志写入到磁盘的文件中。当日志很多,这种频繁操作文件显然性能很低下
4.RollingFileAppender 是一个非常有意思的输出器。它将log信息写入一个文件后,会判断是否满足封存文件的要求,若满足,则除非封存文件的动作。
5.immediateFlush:log4j2接收到日志事件时,是否立即将日志刷到磁盘。默认为true。
6.BufferedIO: 文件流写出是否使用缓冲,true表示使用,默认值为false即不使用缓冲。测试显示,即使在启用immediateFlush的情况下,设置bufferedIO=true也能提高性能。
7.多个 Logger 配置重复了,在日志文件中会重复

补充

PatternLayout定义了输出日志时的格式

%d{HH:mm:ss.SSS} 表示输出到毫秒的时间
%t 输出当前线程名称
%-5level 输出日志级别,-5表示左对齐并且固定输出5个字符,如果不足在右边补0
%logger 输出logger名称,因为Root Logger没有名称,所以没有输出
%msg 日志文本
%n 换行

其他常用的占位符有:
%F 输出所在的类文件名,如Client.java
%L 输出行号
%M 输出所在方法名
%l  输出语句所在的行数, 包括类名、方法名、文件名、行数
--------------------- 
作者:大雨将至 
来源:CSDN 
原文:https://blog.csdn.net/autfish/article/details/51203709 
版权声明:本文为博主原创文章,转载请附上博文链接!

参考

猜你喜欢

转载自www.cnblogs.com/michael-xiang/p/10582300.html