前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

一、日志框架的选择

1、日志选择

Slf4j 是为 Java 提供的简单日志门面。它允许用户以自己的喜好,在工程中通过 Slf4j 接入不同的日志系统。

现在常用的是 logbacklog4j2,其中logbackslf4j 的原生实现框架,与 log4j相比性能更加出众,

spring boot 默认是支持 logback 的;log4j2 出生更晚,已经不仅仅是 og4j 的升级,它还参考了 logback的设计,并且据说在异步方面性能更加出众。如果需要用 log4j2,需要在相关的 ` spring 包里剔除 log相关的依赖。

<!-- Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!-- 如果在使用自带tomcat请注释下面,如果使用第三方tomcat不要注释下面 -->
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
        <exclusion>
            <artifactId>logback-classic</artifactId>
            <groupId>ch.qos.logback</groupId>
        </exclusion>
    </exclusions>
</dependency>

二、Logback

1、logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!--学习 https://blog.csdn.net/ZYC88888/article/details/85060315-->

    <!--
     格式化输出:%d表示日期,
     %thread表示线程名,
     %-5level:级别从左显示5个字符宽度,
     %logger{50} 表示 Logger 名字最长36个字符,
     %msg:日志消息,
     %M : 日志输出所在方法名
     %L : 日志输出所在行数
     %n是换行符 -->
    -->
    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level -[%-32X{REQ_UID}] - %msg  -%logger{50}.%M[%L]%n "/>
    <property name="LOG_PATH" value="/Users/healerjean/Desktop/logs"/>
    <property name="FILE_PATH_INFO"  value="${LOG_PATH}/hlj-logback.log"/>
    <property name="FILE_PATH_ERROR" value="${LOG_PATH}/hlj-logback-error.log"/>
    <property name="FILE_BIZ" value="${LOG_PATH}/hlj-logback-biz.log"/>

    <!--控制台-->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="com.hlj.proj.controller.config.LogbackJsonFilter"/>
        <encoder charset="UTF-8"  >
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>


    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--日志文件输出的文件名 -->
        <File>${FILE_PATH_INFO}</File>
        <!--滚动日志 基于时间和文件大小-->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 滚动日志文件保存格式 i是超出文件大小MaxFileSize 讲历史日志后缀名从0开始起步,
            如果超过了最大的totalSizeCap,就会全部删除,重新开始-->
            <FileNamePattern>${FILE_PATH_INFO}.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxFileSize>1MB</MaxFileSize>
            <totalSizeCap>5GB</totalSizeCap>
            <!--日志最大的历史 10天 -->
            <MaxHistory>10</MaxHistory>
        </rollingPolicy>
        <!-- 按临界值过滤日志:低于INFO以下级别被抛弃 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>
    <appender name="ASYNC_FILE_INFO" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 1. 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>8192</queueSize>
        <!-- 2. 队列剩余容量小于discardingThreshold,则会丢弃TRACT、DEBUG、INFO级别的日志;默认值-1,为queueSize的20%;0不丢失日志 -->
        <discardingThreshold>-1</discardingThreshold>
        <!-- 3. 默认:false,如果系统异常之后,error级别的日志把队列占满了,会出现阻塞情况。可以设置为true,丢弃日志,从而不影响业务线程。 -->
        <neverBlock>true</neverBlock>
        <!--是否提取调用者数据-->
        <includeCallerData>false</includeCallerData>
        <!-- 一个异步appender 只能对应一个同步的appender。 -->
        <appender-ref ref="INFO_FILE"/>
    </appender>


    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${FILE_PATH_ERROR}</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${FILE_PATH_ERROR}.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxFileSize>60MB</MaxFileSize>
            <totalSizeCap>5GB</totalSizeCap>
            <MaxHistory>10</MaxHistory>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>
    <appender name="ASYNC_ERROR_FILE" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 1. 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>8192</queueSize>
        <!-- 2. 队列剩余容量小于discardingThreshold,则会丢弃TRACT、DEBUG、INFO级别的日志;默认值-1,为queueSize的20%;0不丢失日志 -->
        <discardingThreshold>-1</discardingThreshold>
        <!-- 3. 默认:false,如果系统异常之后,error级别的日志把队列占满了,会出现阻塞情况。可以设置为true,丢弃日志,从而不影响业务线程。 -->
        <neverBlock>true</neverBlock>
        <!--是否提取调用者数据-->
        <includeCallerData>false</includeCallerData>
        <!-- 一个异步appender 只能对应一个同步的appender。 -->
        <appender-ref ref="ERROR_FILE"/>
    </appender>







    <appender name="BIZ_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${FILE_BIZ}</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <FileNamePattern>${FILE_BIZ}.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
            <MaxFileSize>60MB</MaxFileSize>
            <totalSizeCap>5GB</totalSizeCap>
            <MaxHistory>10</MaxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
        </encoder>
    </appender>
    <appender name="ASYNC_BIZ_FILE" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 1. 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>8192</queueSize>
        <!-- 2. 队列剩余容量小于discardingThreshold,则会丢弃TRACT、DEBUG、INFO级别的日志;默认值-1,为queueSize的20%;0不丢失日志 -->
        <discardingThreshold>-1</discardingThreshold>
        <!-- 3. 默认:false,如果系统异常之后,error级别的日志把队列占满了,会出现阻塞情况。可以设置为true,丢弃日志,从而不影响业务线程。 -->
        <neverBlock>true</neverBlock>
        <!--是否提取调用者数据-->
        <includeCallerData>false</includeCallerData>
        <!-- 一个异步appender 只能对应一个同步的appender。 -->
        <appender-ref ref="BIZ_FILE"/>
    </appender>
    <logger name="TRADE_LOG" additivity="false" level="INFO">
        <appender-ref ref="BIZ_FILE"/>
    </logger>




    <!--以配置文件application.properties 中为主,如果配置文件中不存在以它为主-->
    <root level="debug">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="ASYNC_ERROR_FILE"/>
        <appender-ref ref="ASYNC_FILE_INFO"/>
    </root>
</configuration>

2、Logback日志到数据库

1)创建数据库表

DROP TABLE IF EXISTS logging_event_property;
DROP TABLE IF EXISTS logging_event_exception;
DROP TABLE IF EXISTS logging_event;


CREATE TABLE logging_event
(
  timestmp          BIGINT       NOT NULL,
  formatted_message TEXT         NOT NULL,
  logger_name       VARCHAR(254) NOT NULL,
  level_string      VARCHAR(254) NOT NULL,
  thread_name       VARCHAR(254),
  reference_flag    SMALLINT,
  arg0              VARCHAR(254),
  arg1              VARCHAR(254),
  arg2              VARCHAR(254),
  arg3              VARCHAR(254),
  caller_filename   VARCHAR(254) NOT NULL,
  caller_class      VARCHAR(254) NOT NULL,
  caller_method     VARCHAR(254) NOT NULL,
  caller_line       CHAR(4)      NOT NULL,
  event_id          BIGINT       NOT NULL AUTO_INCREMENT PRIMARY KEY
)


CREATE TABLE logging_event_property
(
event_id          BIGINT NOT NULL,
mapped_key        VARCHAR(150) NOT NULL,
mapped_value      TEXT,
PRIMARY KEY(event_id, mapped_key),
FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
);

CREATE TABLE logging_event_exception
(
event_id         BIGINT NOT NULL,
i                SMALLINT NOT NULL,
trace_line       VARCHAR(254) NOT NULL,
PRIMARY KEY(event_id, i),
FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
);



2)日志配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

  
 <!--日志异步到数据库 -->
    <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
        <!--日志异步到数据库-->
        <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
            <driverClass>com.mysql.jdbc.Driver</driverClass>
            <url>jdbc:mysql://localhost:3306/healerjean?useUnicode=true&amp;allowMultiQueries=true&amp;characterEncoding=utf8&amp;zeroDateTimeBehavior=convertToNull&amp;useSSL=false</url>
            <user>healerjean</user>
            <password>healerjean</password>
        </connectionSource>
    </appender>

    <root level="info">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="DB"/>
    </root>
</configuration>

3)查看日志

SELECT * from logging_event;

WX20180910-123004

3、常见功能

1)LogBack 打印 Json 数据

<!--控制台-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="com.hlj.proj.controller.config.LogbackJsonFilter"/>
    <encoder charset="UTF-8"  >
        <pattern>${LOG_PATTERN}</pattern>
    </encoder>
</appender>
package com.hlj.proj.controller.config;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;
import com.hlj.proj.controller.utils.JsonUtils;


public class LogbackJsonFilter extends Filter<ILoggingEvent> {
    @Override
    public FilterReply decide(ILoggingEvent event) {
        if (event.getLoggerName().startsWith("com.hlj")) {
            Object[] params = event.getArgumentArray();
            for (int index = 0; index < params.length; index++) {
                Object param = params[index];
                // class.isPrimitive() 8种基本类型的时候为 true,其他为false
                if (!param.getClass().isPrimitive()) {
                    params[index] = JsonUtils.toJsonString(param);
                }
            }
        }
        return FilterReply.ACCEPT;
    }
}

2)行号打印是问号

<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
	
  <!- 加上下面这行 -->
  <includeCallerData>true</includeCallerData>
</appender>

3)自定义 Appender 发送到 MQ

@EqualsAndHashCode(callSuper = true)
@Data
public class MqAppender extends  UnsynchronizedAppenderBase<ILoggingEvent>{

    /**
     * layout
     */
    private Layout<ILoggingEvent> layout;

    /**
     * params
     */
    private String params;


    /**
     *
     */
    @Override
    public void start(){
        //这里可以做些初始化判断 比如layout不能为null ,
        if(layout == null) {
            addWarn("Layout was not defined");
        }
        //或者写入数据库 或者redis时 初始化连接等等
        super.start();
    }


    @Override
    public void stop()
    {
        //释放相关资源,如数据库连接,redis线程池等等
        System.out.println("logback-stop方法被调用");
        if(!isStarted()) {
            return;
        }
        super.stop();
    }

    @Override
    public void append(ILoggingEvent event) {
        if (event == null || !isStarted()){
            return;
        }
        // 此处自定义实现输出
        // 日志信息
        String logInfo = layout.doLayout(event);

        // 打印信息
        String message = event.getMessage();
        System.out.print(params + ":" + logInfo);
        System.out.print(params + ":" + message);

    }
}
<!-- 自定义输出 -->
<appender name="MQ_APPENDER"  class="com.hlj.proj.controller.log.plugin.MqAppender">
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
        <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
            <marker>MARKER_MQ_LOG</marker>
        </evaluator>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <!-- 日志收集最低日志级别 -->
        <level>INFO</level>
    </filter>
    <layout
        class="ch.qos.logback.classic.PatternLayout">
        <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </layout>
    <!-- 自定义参数 -->
    <params>HEALER_JEAN:</params>
</appender>



<!--以配置文件application.properties 中为主,如果配置文件中不存在以它为主-->
<root level="debug">
    <appender-ref ref="STDOUT" />
    <appender-ref ref="ASYNC_ERROR_FILE"/>
    <appender-ref ref="ASYNC_FILE_INFO"/>
    <appender-ref ref="MQ_APPENDER"/>
</root>

三、Log4j

1、log4j.properties

## 必填内容,info/all/.., stdout 为必填,后面的根据log4j.appender.内容进行填写,如果下面有内容则,这里必须加上,
#  level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别。
log4j.rootLogger=info, stdout, log, errorlog,proj



#%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
#%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
#%t: 输出产生该日志事件的线程名
#%C: 输出日志信息所属的类目,通常就是所在类的全名
#%M: 输出代码中指定的消息,产生的日志具体信息
#%F: 输出日志消息产生时所在的文件名称
#%L: 输出代码中的行号
#%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
#%r: 输出自应用启动到输出该log信息耗费的毫秒数
#%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
#%%: 输出一个”%”字符
#%n: 输出一个回车换行符,Windows平台为”\r\n”,Unix平台为”\n”输出日志信息换行
#%hostName : 本地机器名
#%hostAddress : 本地ip地址-->
#可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
#1) c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。
#2)%-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,”-”号指定左对齐。
#3)%.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
#4) .30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边交远销出的字符截掉


# RollingFileAppender按log文件最大长度限度生成新文件
# DailyRollingFileAppender按日期生成新文件,不能根据大小清除历史日志,但是我们可以自定义来实现

# %d{yyyy-MM-dd HH:mm:ss,SSS}日期    %p級別 %t当前线程名称   %m日志信息   [%C.%M]类名加方法    %L行数 %n换行
# 举例 # 2019-07-13 09:05:14,674  [INFO]-[http-nio-8888-exec-1] info日志==================  com.hlj.proj.controler.Log4jController.log4j][25]



# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS}  [%p]-[%t] %m  %C.%M][%L] %n




## 根据日期生成配置文件当前log.log 如果时间超过了设置的格式的时间DatePattern 则会在后面加上    log.log.2019-07-12.log
#  解释:也就是说log文件会暂存每天的日志,到第二天时会再加上yyyy-MM,产生当天的完整日志文件
### Log info
log4j.appender.log = org.apache.log4j.DailyRollingFileAppender
log4j.appender.log.File = /Users/healerjean/Desktop/logs/hlj-log4j.log
log4j.appender.log.Append = true
log4j.appender.log.Threshold = INFO
#超过日期则讲历史日志加上后缀日期用于区分
log4j.appender.log.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.log.layout = org.apache.log4j.PatternLayout
log4j.appender.log.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS}  [%p]-[%t] %m  %C.%M][%L] %n





## 5  按照文件大小进行日志切分 文件历史日志依次 error.log.1 error.log.2
log4j.appender.errorlog=org.apache.log4j.RollingFileAppender
log4j.appender.errorlog.File=/Users/healerjean/Desktop/logs/error.log
log4j.appender.errorlog.Append=true
log4j.appender.errorlog.Threshold=error
#设置日志文件的大小
log4j.appender.errorlog.MaxFileSize=2000KB
#保存200个备份文件
log4j.appender.errorlog.MaxBackupIndex=200
log4j.appender.errorlog.layout=org.apache.log4j.PatternLayout
log4j.appender.errorlog.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS}   [%p]-[%t] %m  %C.%M][%L %n



log4j.appender.proj=com.hlj.proj.utils.RoolingAndDateFileAppender
log4j.appender.proj.file=/Users/healerjean/Desktop/logs/logRecoed.log
log4j.appender.proj.Append=true
log4j.appender.proj.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.proj.Threshold=error
#设置日志文件的大小
log4j.appender.proj.MaxFileSize=5KB
#最大保留多少个文件,超过之后会进行重新命名,所以尽量不要超过
log4j.appender.proj.maxIndex=10
#只保留多长时间的
log4j.appender.proj.expirDays=1
log4j.appender.proj.layout=org.apache.log4j.PatternLayout
log4j.appender.proj.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS}  [%p]-[%t] %m  %C.%M][%L] %n




四、Log4j2

log4j一直存在两个问题,一是打日志影响到系统性能效率,二是有多线程的时候,日志会比较乱

log4j2log4j 1.x 的升级版,参考了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升,主要有:

异常处理,在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。

性能提升, log4j2相较于log4j 1和logback都具有很明显的性能提升,后面会有官方测试的数据。

自动重载配置,参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产上可以动态的修改日志的级别而不需要重启应用——那对监控来说,是非常敏感的。

无垃圾机制,log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc。

1、log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>


<!--status  Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,
 你会看到log4j2内部各种详细输出。可以设置成OFF(关闭)或Error(只输出错误信息)-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="error" monitorInterval="30">
    <!--    %d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间-->
    <!--    %p : 日志输出格式-->
    <!--    %thread表示线程名,-->
    <!--    %c : logger的名称-->
    <!--    %m : 日志内容,即 logger.info("message")-->
    <!--    %n : 换行符-->
    <!--    %C : Java类名-->
    <!--    %L : 日志输出所在行数-->
    <!--    %M : 日志输出所在方法名-->
    <!--    hostName : 本地机器名-->
    <!--    hostAddress : 本地ip地-->

    <!-- 日志文件目录和压缩文件目录配置 -->
    <Properties>
        <Property name="level">info</Property>
        <Property name="LOG_PATTERN">
            %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level -[%-32X{REQ_UID}]- %msg%xEx %logger{36}.%M[%L]%n
        </Property>

        <Property name="logDri">/Users/healerjean/Desktop/logs</Property>
        <Property name="logFileName">hlj-client</Property>

        <Property name="infoLogDri">${logDri}/info</Property>
        <Property name="infoLogGz">${infoLogDri}/gz</Property>
        <Property name="infoLogFileName">${logFileName}.log</Property>

        <Property name="errorLogDri">${logDri}/error</Property>
        <Property name="errorLogGz">${errorLogDri}/gz</Property>
        <Property name="errorLogFileName">${logFileName}.error</Property>

    </Properties>

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


        <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingRandomAccessFile name="infoFile" fileName="${infoLogDri}/${infoLogFileName}"
                                 filePattern="${infoLogGz}/$${date:yyyy-MM}/%d{yyyy-MM-dd}-%i.${infoLogFileName}.gz">
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!-- 基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小 -->
                <SizeBasedTriggeringPolicy size="500 MB"/>
                <!-- 基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour -->
                <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
            </Policies>
            <Filters>
                <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)
                onMatch属性设置为DENY,过滤掉高等级的日志;onMismatch设置为NEUTRAL,把低等级的日志放行,
                -->
                <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <!-- 指定每天(文件夹是以天的,看上面的)的最大压缩包个数,默认7个,超过了会覆盖之前的(用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)) -->
            <DefaultRolloverStrategy max="2000"/>
        </RollingRandomAccessFile>


        <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingRandomAccessFile name="errorFile" fileName="${errorLogDri}/${errorLogFileName}"
                                 filePattern="${errorLogGz}/$${date:yyyy-MM}/%d{yyyy-MM-dd}-%i.${errorLogFileName}.gz">
            <PatternLayout pattern="${LOG_PATTERN}"/>
            <Policies>
                <!-- 基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小 -->
                <SizeBasedTriggeringPolicy size="500 MB"/>
                <!-- 基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour -->
                <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
            </Policies>
            <Filters>
                <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)
                onMatch属性设置为DENY,过滤掉高等级的日志;onMismatch设置为NEUTRAL,把低等级的日志放行,
                -->
                <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <!-- 指定每天(文件夹是以天的,看上面的)的最大压缩包个数,默认7个,超过了会覆盖之前的(用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)) -->
            <DefaultRolloverStrategy max="2000"/>
        </RollingRandomAccessFile>

    </appenders>


    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <!-- AsyncRoot - 异步记录日志 - 需要LMAX Disruptor的支持 -->
        <!-- additivity如果设置为true将会输出两次日志,意思和log4j里面意思是否追加 -->
        <AsyncRoot level="${level}" additivity="false" includeLocation="true">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="infoFile"/>
            <AppenderRef ref="errorFile"/>
        </AsyncRoot>
    </loggers>


</configuration>

1)日志打印位置

main方法和服务器日志都在一起

image-20200612153846792

image-20200612153853073

image-20200612153900308

image-20200612153907611

2、修改日志级别

1)修改包路径日志级别

a、properties 修改:

server.port=8888


logging.config=classpath:log4j2.xml
logging.level.com.hlj.proj.controller.Log4j2Controller: error

b、log4j2.xml 修改

<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>

    <logger name="com.hlj.proj.controller"  level="ERROR"/>

    <!-- AsyncRoot - 异步记录日志 - 需要LMAX Disruptor的支持 -->
    <!-- additivity如果设置为true将会输出两次日志,意思和log4j里面意思是否追加 -->
    <AsyncRoot level="${level}" additivity="false" includeLocation="true">
        <AppenderRef ref="Console"/>
        <AppenderRef ref="infoFile"/>
        <AppenderRef ref="errorFile"/>
    </AsyncRoot>

    <logger name="businessLog" additivity="false" level="INFO">
        <appender-ref ref="businessLog"/>
    </logger>

</loggers>

2)动态修改日志级别

  @LogIndex
  @GetMapping("updateLevel")
  public String updateLevel(String name, String level) {
      Configurator.setLevel(name, Level.toLevel(level));
      log.debug("debug日志================{},level:{}", name,level);
      log.info("info日志=================={},level:{}", name,level);
      log.warn("warn日志=================={},level:{}", name,level);
      log.error("error日志================{},level:{}", name,level);
      return "修改日志级别成功";
  }

// 全局 http://localhost:8888/hlj/updateLevel?name=&level=INFO
// 包路径 http://localhost:8888/hlj/updateLevel?name=com.hlj.proj.controller&level=DEBUG
// 测试 http://localhost:8888/hlj/log4j2

ContactAuthor