Java日志框架JUL、Log4j、logback、log4j2使用

随着软件系统的发展系统业务越来越多、逻辑越来越复杂、代码量越来越多,伴随着容易出现的bug也会越来越多,不论是开发测试阶段还是生产阶段都需要将这些错误及时的捕捉记录下来,方便解决这些问题,否则针对出现的异常无从下手;此时就需要一些日志框架来完成这些事情并且最好能在出现问题时自动捕捉而不需要代码额外的处理,比如记录哪些类型的错误、日志格式、日志分类、日志扩展等等;一般Java有以下日志框架可选择,日志实现:JUL、logback、log4j、log4j2,日志门面:JCL、slf4j。
日志框架:用于记录日志的具体实现组件。
日志门面:因为每种日志框架记录日志的API各不相同,在使用某种日志框架时就需要使用它特定的API记录日志,如果项目后期改用其他框架那么就会导致改动很多记录日志的代码,所以通过日志门面进行统一API接口各种框架实现接口,那么即使更换框架日志记录也是一样的API,不需要做修改。

日志实现

一、JUL

JUL全称Java util Logging是java原生的日志框架,使用时不需要另外引用第三方类库,使用方便,学习简单(位于java.util.logging包下面)。

1、简单使用

两步:

//获取Logger对象,com.test.nginx.nginxtest.TestController需要输出日志的类全限定路径(当前类全限定路径)
Logger log = Logger.getLogger("com.test.nginx.nginxtest.TestController");
//输出日志
log.info("info");

代码:

package com.test.nginx.nginxtest;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.logging.*;

@RequestMapping("/nginx")
@RestController
public class TestController {
    //获取Logger对象,Logger对象存在父子级关系,对父级Logger对象的设置,子对象同样生效,通过路径组织Logger对象的父子级关系,比如 com.test.nginx 是 com.test 的子级
    //即对Logger.getLogger("com.test") 对象的设置,对Logger.getLogger("com.test.nginx")对象同样生效,最顶级父对象是LogManager$RootLogger
    private final Logger log = Logger.getLogger("com.test.nginx.nginxtest.TestController");

    @GetMapping("/test/{value}")
    public String test(@PathVariable("value") String value){
        //设置日志输出级别,默认是info级别,即info和高于info级别的日志才会输出
        //关闭默认级别
        log.setUseParentHandlers(false);
        //ConsoleHandler控制台输出
        ConsoleHandler consoleHandler = new ConsoleHandler();
        SimpleFormatter simpleFormatter = new SimpleFormatter();
        consoleHandler.setFormatter(simpleFormatter);
        log.addHandler(consoleHandler);
        //设置日志级别为ALL,表示所有级别的日志都进行输出
        log.setLevel(Level.ALL);
        consoleHandler.setLevel(Level.ALL);
        try {
            //FileHandler文件输出,E:\nginx-test\logs\jul.log文件需要已存在
            FileHandler fileHandler = new FileHandler("E:\\nginx-test\\logs\\jul.log");
            fileHandler.setFormatter(simpleFormatter);
            log.addHandler(fileHandler);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String a = "a对象";
        Integer b = 2;
        //输出severe级别的日志,相当于error日志
        log.severe("severe");
        //统一输出日志方法,日志级别通过参数控制,可以通过占位符替换日志中的参数
        log.log(Level.WARNING,"日志输出:{0},大小{1}",new Object[]{a,b});
        log.info("info");
        log.config("config");
        log.fine("fine");
        log.finer("finer");
        log.finest("finest");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(log.getParent());
        return "你好8081,"+value;
    }

}

Java日志框架JUL、Log4j、logback、log4j2使用_第1张图片

2、配置文件方式使用

既然JUL是Java原生的日志框架,最顶级父类是 LogManager$RootLogger 意味着jdk内部应当集成了这个最顶级父类的默认配置文件,从而实现Logger对象的默认配置,这个配置文件在 JAVA_HOME 目录下(比如我的 JAVA_HOME 目录是 C:\Program Files\Java\jdk1.8.0_191 ,那么该配置文件所在位置是 C:\Program Files\Java\jdk1.8.0_191\jre\lib\logging.properties )
配置文件主要内容如下:

############################################################
#  	Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.  
# For example java -Djava.util.logging.config.file=myfile
############################################################

############################################################
#  	Global properties
############################################################

# "handlers" specifies a comma separated list of log Handler 
# classes.  These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler   #指定处理器为ConsoleHandler,可以写多个如(也就是该配置决定在使用JUL记录日志时使用的Handler即开启哪个Handler,java.util.logging.ConsoleHandler表示在控制台输出日志,java.util.logging.FileHandler表示在文件中输出日志,需要控制台和文件中都输出日志则两个处理器都要写):
#handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler

# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers.  For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO   #指定日志级别
#如果没有指定具体的Logger名称表示对顶级父类 LogManager$RootLogger 的设置,比如上面的 handlers 和 .level 都是对顶级父类的配置,如果写了名称比如 com.handlers= java.util.logging.ConsoleHandler    com.level= INFO 则表示该配置是对com这个Logger对象的配置(当然它的子类也生效),注意需要对 com 这个 Logger 对象关闭默认配置 com.useParentHandlers = false

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################

# default file output is in user's home directory.
#java.util.logging.FileHandler 表示对 FileHandler(文件日志处理器) 处理器的配置
java.util.logging.FileHandler.pattern = %h/java%u.log   #指定日志文件保存位置及日志文件名称 %h 当前目录,%u 表示数字几
java.util.logging.FileHandler.limit = 50000   #指定每个日志文件记录50000条日志
java.util.logging.FileHandler.count = 1    #指定日志文件个数比如9表示9个日志文件,那么上面的 %u 分别为0-8
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter   #指定文件日志输出日志格式对象
java.util.logging.FileHandler.append = true  #通过追加的形式将日志记录到文件日志中,否则之前的日志会被下一次的日志覆盖

# Limit the message that are printed on the console to INFO and above.
#java.util.logging.ConsoleHandler 表示对 ConsoleHandler(控制台日志处理器) 处理器的配置
java.util.logging.ConsoleHandler.level = INFO   #指定控制台输出日志级别
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter   #指定控制台输出日志格式对象
java.util.logging.ConsoleHandler.encoding = UTF-8  #指定控制台输出日志编码
#java.util.logging.SimpleFormatter 表示对 SimpleFormatter (简单日志格式对象)的设置
java.util.logging.SimpleFormatter.format = %4$s: %5$s [%1$tc]%n  #指定 SimpleFormatter 日志格式

# Example to customize the SimpleFormatter output format 
# to print one-line log message like this:
#     :  []
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n

############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################

# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
com.xyz.foo.level = SEVERE

在项目的resources目录下创建 logging.properties 文件并定义好配置
编码:

public static void main(String[] args) {
        //读取配置文件获取输入流
        InputStream resourceAsStream = TestJULController.class.getClassLoader().getResourceAsStream("logging.properties");
        //获取 LogManager 对象
        LogManager logManager = LogManager.getLogManager();
        try {
            //设置 LogManager 对象读取 resourceAsStream 
            logManager.readConfiguration(resourceAsStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        final Logger log = Logger.getLogger("com.test.nginx.nginxtest.TestJULController");
        String a = "a对象";
        Integer b = 2;
        log.severe("severe");
        log.log(Level.WARNING,"日志输出:{0},大小{1}",new Object[]{a,b});
        log.info("info");
        log.config("config");
        log.fine("fine");
        log.finer("finer");
        log.finest("finest");
    }

这是编码方式使用配置文件,一般spring boot项目用文章最后方式使用。

二、Log4j

Log4j是Apache下的一款开源的日志框架,通过在项目中使用 Log4J,可以控制日志信息输出到控制台、文件、数据库中;可以设置日志输出格式、日志输出级别。官网 (位于org.apache.log4j包下面)

导入包

        <dependency>
            <groupId>log4jgroupId>
            <artifactId>log4jartifactId>
            <version>1.2.17version>
        dependency>

1、简单使用

package com.test.nginx.nginxtest;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/log4j")
@RestController
public class TestLog4jController {


    @GetMapping("/test/{value}")
    public String test(@PathVariable("value") String value){

        return "你好8081,"+value;
    }

    public static void main(String[] args) {
        //不使用配置文件需要初始化系统配置
        BasicConfigurator.configure();
        //获取Logger对象,可以使用需要打印日志的类的 Class 对象或类的全路径
        Logger log = Logger.getLogger(TestLog4jController.class);
        //打印日志,优先级从上到下依次降低,默认日志级别是 debug 
        log.log(Level.FATAL,"日志输出:fatal信息");  // 严重错误,一般会造成系统崩溃和终止运行,一般不打印这种级别的日志
        log.error("日志输出:error信息");  //错误信息,但不会影响系统运行,也就是业务处理报错,但不会导致系统崩溃
        log.warn("日志输出:warn信息");  //警告信息,可能会发生问题
        log.info("日志输出:info信息");  //程序运行信息,数据库的连接、网络、IO操作等,程序正常运行且未有异常记录的日志
        log.debug("日志输出:debug信息");  //调试信息,一般在开发阶段使用,记录程序的变量、参数等
        log.trace("日志输出:trace信息");  //追踪信息,记录程序的所有流程信息,六种日志级别,一般不记录fatal和trace级别的日志,其余四种较常用,另外还有 OFF级别 用来关闭日志记录和 ALL级别 启用所有消息的日志记录
    }

}

2、配置文件使用

在项目的resources目录下创建 log4j.properties 文件并定义好配置

log4j.rootLogger = trace,console,dailyFile,logDB    #定义日志输出级别和输出类型,trace是日志级别,console和dailyFile、logDB是日志输出类型(输出到控制台)和文件中(DailyRollingFileAppender类型按照时间拆分日志)、数据库中,console和dailyFile、logDB是和下面定义的每种Appender名称对应的,这个名称可以自定义
#定义控制台类型日志信息,console是ConsoleAppender
log4j.appender.console = org.apache.log4j.ConsoleAppender    #定义日志输出console类型的Appender
log4j.appender.console.layout = org.apache.log4j.PatternLayout   #定义日志输出console类型的layout(格式)为PatternLayou(可自定义格式)
log4j.appender.console.layout.conversionPattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %l - %m%n   #自定义日志输出格式

#自定义Logger,同样的Log4j中rootLogger是最顶级的父类,只要配置rootLogger之后,那么所有的类输出日志时都会按照rootLogger定义的日志级别和日志类型输出,如果想要不同包下面的类分开设置日志级别和日志类型,就可以采用自定义Logger实现,比如下面就是对于com.test.nginx.nginxtest包下面的输出info及以上级别的日志并且输出到file中,对于org.apache下面的类输出error及以上级别的日志(对于日志级别子类会覆盖rootLogger设置的日志级别,对于输出类型则是并集,比如这里rootLogger定义了console,dailyFile,logDB三种类型,那么org.apache和com.test.nginx.nginxtest包下面的类都有这三种类型日志,并且com.test.nginx.nginxtest还多一个file类型的日志)
log4j.logger.com.test.nginx.nginxtest = info,file
log4j.logger.org.apache = error

#定义文件类型日志信息,file是FileAppender,将日志都输出在一个文件中
log4j.appender.file = org.apache.log4j.FileAppender
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.conversionPattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %l - %m%n
log4j.appender.file.file = logs/log4j.log  #文件日志位置,不是 / 开头表示相对位置
log4j.appender.file.encoding = UTF-8   #设置日志编码

#定义文件类型日志信息,rollingFile是RollingFileAppender,可以根据日志文件大小将日志拆分为多个文件
log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.conversionPattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %l - %m%n
log4j.appender.rollingFile.file = logs/log4j.log
log4j.appender.rollingFile.encoding = UTF-8
log4j.appender.rollingFile.maxFileSize = 4KB  #设置每个日志文件大小
log4j.appender.rollingFile.maxBackupIndex = 7  #设置日志文件总个数

#定义文件类型日志信息,dailyFile是DailyRollingFileAppender,将日志根据时间输出在多个文件中,具体文件名称中时间部分由log4j.appender.dailyFile.datePattern参数定义
log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout
log4j.appender.dailyFile.layout.conversionPattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %l - %m%n
log4j.appender.dailyFile.file = logs/log4j.log
log4j.appender.dailyFile.encoding = UTF-8
log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss  #定义日志文件名称中日期格式,当前是精确到时分秒,那么不同日期不同时分秒的日志输出在多个文件中

#定义输出到数据库类型日志信息,logDB是JDBCAppender,将日志输出到定义的数据库中,插入内容由log4j.appender.logDB.Sql定义的sql决定
log4j.appender.logDB=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout=org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver=com.mysql.cj.jdbc.Driver   #定义数据库驱动
log4j.appender.logDB.URL=jdbc:mysql://127.0.0.1:3306/test?setUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true   #数据库url
log4j.appender.logDB.User=root  #数据库账号
log4j.appender.logDB.Password=root   #数据库密码
log4j.appender.logDB.Sql=INSERT INTO log(project_name,create_date,level,category,file_name,thread_name,line,all_category,message) values('itcast','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')   #插入日志sql

定义为sql类型日志,需要在对应数据库中创建log表:

CREATE TABLE `log` (
`log_id` int(11) NOT NULL AUTO_INCREMENT,
`project_name` varchar(255) DEFAULT NULL COMMENT '目项名',
`create_date` varchar(255) DEFAULT NULL COMMENT '创建时间',
`level` varchar(255) DEFAULT NULL COMMENT '优先级',
`category` varchar(255) DEFAULT NULL COMMENT '所在类的全名',
`file_name` varchar(255) DEFAULT NULL COMMENT '输出日志消息产生时所在的文件名称 ',
`thread_name` varchar(255) DEFAULT NULL COMMENT '日志事件的线程名',
`line` varchar(255) DEFAULT NULL COMMENT '号行',
`all_category` varchar(255) DEFAULT NULL COMMENT '日志事件的发生位置',
`message` varchar(4000) DEFAULT NULL COMMENT '输出代码中指定的消息',
PRIMARY KEY (`log_id`)
);

定义为sql类型日志,需要在项目中导入数据库驱动jar包:

        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <version>8.0.22version>
        dependency>

编码:

package com.test.nginx.nginxtest;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/log4j")
@RestController
public class TestLog4jController {


    @GetMapping("/test/{value}")
    public String test(@PathVariable("value") String value){

        return "你好8081,"+value;
    }

    public static void main(String[] args) {
        //BasicConfigurator.configure();  不使用配置文件需要初始化系统配置,如果使用配置文件则不需要
        LogLog.setInternalDebugging(true);  //开启Log4j内部日志输出(也就是会输出Log4j本身初始化运行等日志)
        Logger log = Logger.getLogger("com.test.nginx.nginxtest.TestLog4jController");
        log.log(Level.FATAL,"日志输出:fatal信息");
        log.error("日志输出:error信息");
        log.warn("日志输出:warn信息");
        log.info("日志输出:info信息");
        log.debug("日志输出:debug信息");
        log.trace("日志输出:trace信息");
    }

}

在这里插入图片描述
Java日志框架JUL、Log4j、logback、log4j2使用_第2张图片
常见的Appender:

ConsoleAppender  将日志输出到控制台
FileAppender  将日志输出到文件中
DailyRollingFileAppender  将日志输出到一个日志文件,并且每天输出到一个新的文件
RollingFileAppender  将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件
JDBCAppender  把日志信息保存到数据库中

三种常见的Layout:

HTMLLayout  格式化日志输出为HTML表格形式   org.apache.log4j.HTMLLayout
SimpleLayout  简单的日志输出格式化,打印的日志格式为(info - message)org.apache.log4j.SimpleLayout
PatternLayout   最强大的格式化期,可以根据自定义格式输出日志,如果没有指定转换格式,就是用默认的转换格式(默认格式比SimpleLayout更简单)org.apache.log4j.PatternLayout
XMLLayout  格式化日志输出为xml格式,不常用  org.apache.log4j.xml.XMLLayout

自定义格式 conversionPattern 取值:

%m 输出代码中指定的日志信息
%p 输出优先级,及 DEBUG、INFO 等
%n 换行符(Windows平台的换行符为 "\n",Unix 平台为 "\n")
%r 输出自应用启动到输出该 log 信息耗费的毫秒数
%c 输出打印语句所属的类的全名
%t 输出产生该日志的线程全名
%d 输出服务器当前时间,默认为 ISO8601,也可以指定格式,如:%d{yyyy年MM月dd日HH:mm:ss}
%l 输出日志时间发生的位置,包括类名、线程、及在代码中的行数。如:Test.main(Test.java:10)
%F 输出日志消息产生时所在的文件名称
%L 输出代码中的行号
%% 输出一个 "%" 字符



另外可以在 % 与字符之间加上修饰符来控制最小宽度、最大宽度和文本的对其方式。如:
%5c 输出category名称,最小宽度是5,category<5,默认的情况下右对齐
%-5c 输出category名称,最小宽度是5,category<5,"-"号指定左对齐,会有空格
%.5c 输出category名称,最大宽度是5,category>5,就会将左边多出的字符截掉,<5不会有空格
%20.30c category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉

三、logback

Logback是由log4j创始人设计的另一个开源日志组件,性能比log4j要好。官网
Logback主要有三个模块:
1、logback-core:其它两个模块的基础模块
2、logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API
3、logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能

导入包

        
        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-classicartifactId>
            <version>1.2.3version>
        dependency>

1、简单使用

代码:

package com.test.nexus;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestSlf4j {
    public static void main(String[] args) {

        Logger logger = LoggerFactory.getLogger(TestSlf4j.class);
        //slf4j没有 fatal 级别的日志
        logger.error("日志输出:error信息");
        logger.warn("日志输出:warn信息");
        logger.info("日志输出:info信息");
        logger.debug("日志输出:debug信息");
        logger.trace("日志输出:trace信息");
        try {
            throw new NullPointerException("空指针!");
        }catch (Exception e){
            logger.error("发生异常:",e);
        }

    }
}

Java日志框架JUL、Log4j、logback、log4j2使用_第3张图片

2、配置文件使用

logback会依次读取以下类型配置文件:
1、logback.groovy
2、logback-test.xml
3、logback.xml 如果均不存在会采用默认配置

logback组件之间的关系

  1. Logger:日志的记录器,把它关联到应用的对应的context上后,主要用于存放日志对象,也可以定义日志类型、级别。
  2. Appender:用于指定日志输出的目的地,目的地可以是控制台、文件、数据库等等。
  3. Layout:负责把事件转换成字符串,格式化的日志信息的输出。在logback中Layout对象被封装在encoder中(也就是说需要配置Layout时就通过配置encoder实现)。

在 resources 下创建 logback.xml 配置文件


<configuration>
    
    
    <property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread]  %m%n"/>
    
    
    <property name="log_dir" value="logs">property>
    
    
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        
        <target>System.errtarget>
        
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            
            <pattern>${pattern}pattern>
        encoder>
    appender>

    
    <appender name="file" class="ch.qos.logback.core.FileAppender">
        
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}pattern>
        encoder>
        
        <file>${log_dir}/logback.logfile>
    appender>

    
    <appender name="htmlFile" class="ch.qos.logback.core.FileAppender">
        
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.classic.html.HTMLLayout">
                <pattern>%level%d{yyyy-MM-dd HH:mm:ss}%c%M%L%thread%mpattern>
            layout>
        encoder>
        
        <file>${log_dir}/logback.htmlfile>
    appender>

    
    <appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}pattern>
        encoder>
        
        <file>${log_dir}/roll_logback.logfile>
        
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            
            <fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd}-%i.log.gzfileNamePattern>
            
            <maxFileSize>1MBmaxFileSize>
        rollingPolicy>
        
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            
            <level>infolevel>
            
            <onMatch>ACCEPTonMatch>
            
            <onMismatch>DENYonMismatch>
        filter>
    appender>

    
    <appender name="async" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="rollFile"/>
    appender>

    
    
    <root level="ALL">
        
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
        <appender-ref ref="htmlFile"/>
        <appender-ref ref="rollFile"/>
    root>

    
    
    <logger name="com.test.nexus" level="debug" additivity="false">
        <appender-ref ref="console"/>
    logger>
configuration>

Java日志框架JUL、Log4j、logback、log4j2使用_第4张图片
Java日志框架JUL、Log4j、logback、log4j2使用_第5张图片

四、Log4j2

Apache Log4j 2是对Log4j的升级版,参考了logback的一些优秀的设计,并且修复了一些问题,因此带来了一些重大的提升,主要有:
1、异常处理:在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。
2、性能提升:log4j2相较于log4j 和logback都具有很明显的性能提升。
3、自动重载配置:参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产上可以动态的修改日志的级别而不需要重启应用。
4、无垃圾机制:log4j2在大部分情况下,都可以使用其设计的一套无垃圾机制,避免频繁的日志收集导致的jvm gc。
官网
目前市面上最主流的日志门面就是SLF4J,虽然Log4j2也是日志门面,但它的日志实现功能非常强大,性能优越。所以一般还是将Log4j2看作是日志的实现,采用 Slf4j + Log4j2 是主流日志记录搭配。

导入包

        
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-apiartifactId>
            <version>2.11.1version>
        dependency>
        
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-coreartifactId>
            <version>2.11.1version>
        dependency>

1、简单使用

目前导入的是 log4j-api 日志门面,所以以下代码使用的 Log4j2 的日志门面进行的日志输出

package com.test.nexus;


import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class TestLog4j2 {
    public static void main(String[] args) {

        Logger logger = LogManager.getLogger(TestLog4j2.class);
        logger.fatal("日志输出:fatal信息");
        logger.error("日志输出:error信息");
        logger.warn("日志输出:warn信息");
        logger.info("日志输出:info信息");
        logger.debug("日志输出:debug信息");
        logger.trace("日志输出:trace信息");
    }
}

在这里插入图片描述
使用 Slf4j 日志门面输出日志
导入 Slf4j 相关包

        
        <dependency>
            <groupId>org.apache.logging.log4jgroupId>
            <artifactId>log4j-slf4j-implartifactId>
            <version>2.10.0version>
        dependency>

代码:

package com.test.nexus;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestLog4j2Slf4j {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(TestLog4j2Slf4j.class);
        //slf4j没有 fatal 级别的日志
        logger.error("日志输出:error信息");
        logger.warn("日志输出:warn信息");
        logger.info("日志输出:info信息");
        logger.debug("日志输出:debug信息");
        logger.trace("日志输出:trace信息");
    }
}

在这里插入图片描述

2、配置文件使用

在 resources 目录下创建 log4j2.xml 文件并配置



<Configuration status="warn" monitorInterval="5">

    <properties>
        
        <property name="LOG_HOME">logsproperty>
    properties>

    <Appenders>
        
        <Console name="Console" target="SYSTEM_OUT">
            
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n" />
        Console>
        
        <File name="file" fileName="${LOG_HOME}/myfile.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n" />
        File>

        
        <Async name="Async">
            
            <AppenderRef ref="file"/>
        Async>

        
        <RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n" />
        RandomAccessFile>
        
        <RollingFile name="rollingFile" fileName="${LOG_HOME}/myrollog.log" filePattern="logs/$${date:yyyy-MM-dd}/myrollog-%d{yyyy-MM-dd-HH-mm}-%i.log">
            
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY" />
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %msg%n" />
            
            <Policies>
                
                <OnStartupTriggeringPolicy />
                
                <SizeBasedTriggeringPolicy size="1MB" />
                
                <TimeBasedTriggeringPolicy />
            Policies>
            
            <DefaultRolloverStrategy max="30" />
        RollingFile>
    Appenders>

    
    <Loggers>
        
        <AsyncLogger name="com.test.nexus" level="trace" includeLocation="false" additivity="false">
            <AppenderRef ref="Console"/>
        AsyncLogger>
        
        <Root level="trace">
            
            <AppenderRef ref="Console" />
            <AppenderRef ref="file" />
            <AppenderRef ref="rollingFile"/>
            
            <AppenderRef ref="Async"/>
        Root>
    Loggers>
Configuration>

如果配置异步日志,需要导入异步日志依赖

        
        <dependency>
            <groupId>com.lmaxgroupId>
            <artifactId>disruptorartifactId>
            <version>3.3.4version>
        dependency>

Log4j2提供了两种实现异步日志的方式,一个是通过AsyncAppender,一个是通过AsyncLogger,分别对应Appender组件和Logger组件。
其中 AsyncAppender 方式性能和logback、log4j等差别不大,不建议使用。
AsyncLogger推荐使用,有两种配置方式:
全局异步配置:所有的日志都异步的记录,在配置文件上不用做任何改动,只需要在 resources 目录下添加一个 log4j2.component.properties 文件并加入以下配置即可.

Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

混合异步配置:可以在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活(先关闭全局的 AsyncLogger 否则就是全局异步而非混合异步),在 Loggers 标签中配置 AsyncLogger 信息即可。

    <Loggers>

        <AsyncLogger name="com.test.nexus" level="trace" includeLocation="false" additivity="false">
            <AppenderRef ref="Console"/>
        AsyncLogger>
    Loggers>        

使用异步日志需要注意的问题:

  1. 如果使用异步日志,AsyncAppender、AsyncLogger(包括其中的全局异步和混合异步),不要同时出现。性能会和AsyncAppender一致,降至最低。
  2. 设置includeLocation=false ,打印位置信息(输出日志的代码行号)会急剧降低异步日志的性能,比同步日志还要慢。
    Java日志框架JUL、Log4j、logback、log4j2使用_第6张图片
    Java日志框架JUL、Log4j、logback、log4j2使用_第7张图片
    Java日志框架JUL、Log4j、logback、log4j2使用_第8张图片
    无垃圾模式
    垃圾收集暂停是延迟峰值的常见原因,并且对于许多系统而言,花费大量精力来控制这些暂停,许多日志库(包括以前版本的Log4j)在稳态日志记录期间分配临时对象,如日志事件对象,字符串,字符数组,字节数组等;这会对垃圾收集器造成压力并增加GC暂停发生的频率。所以从版本2.6开始,默认情况下Log4j以“无垃圾”模式运行,其中重用对象和缓冲区,并且尽可能不分配临时对象。还有一个“低垃圾”模式,它不是完全无垃圾,但不使用ThreadLocal字段。Log4j 2.6中的无垃圾日志记录部分通过重用ThreadLocal字段中的对象来实现,部分通过在将文本转换为字节时重用缓冲区来实现。
    Log4j 2.5:内存分配速率809 MB /秒,141个无效集合。
    Log4j 2.6:没有分配临时对象,0(零)垃圾回收。
    有两个单独的系统属性可用于手动控制Log4j用于避免创建临时对象的机制:
    log4j2.enableThreadlocals - 如果“true”(非Web应用程序的默认值)对象存储在ThreadLocal字段中并重新使用,否则将为每个日志事件创建新对象。
    log4j2.enableDirectEncoders - 如果将“true”(默认)日志事件转换为文本,则将此文本转换为字节而不创建临时对象。注意: 由于共享缓冲区上的同步,在此模式下多线程应用程序的同步日志记录性能可能更差。如果您的应用程序是多线程的并且日志记录性能很重要,请考虑使用异步记录器。
    这些都不需要手动设置,只需要将 log4j2 的版本升级为 2.6 及以上即可。 也就是使用log4j2作为日志实现时使用2.6及以上的版本,并可以采用 AsyncLogger 的全局或混合异步提升性能。

日志门面

JCL和SLF4J
日志门面技术作用:

  1. 面向接口开发,不再依赖具体的实现类。减少代码的耦合
  2. 项目通过导入不同的日志实现类,可以灵活的切换日志框架
  3. 统一API,方便开发者学习和使用
  4. 统一配置便于项目日志的管理

一、JCL

全称Jakarta Commons Logging,是Apache提供的一个通用日志API,它是为 "所有的Java日志实现"提供一个统一的接口,它自身也提供一个日志的实现,但是功能非常常弱(SimpleLog)。一般不会单独使用它,允许开发人员使用不同的具体日志实现工具: Log4j和jdk自带的日志(JUL)。
JCL 有两个基本的抽象类:Log(基本记录器)和LogFactory(负责创建Log实例)。

导入JCL jar包

        <dependency>
            <groupId>commons-logginggroupId>
            <artifactId>commons-loggingartifactId>
            <version>1.2version>
        dependency>

编写使用日志代码:

package com.test;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TestSec {

    public static void main(String[] args) {
        Log log = LogFactory.getLog(TestSec.class);
        log.fatal("日志输出:fatal信息");
        log.error("日志输出:error信息");
        log.warn("日志输出:warn信息");
        log.info("日志输出:info信息");
        log.debug("日志输出:debug信息");
        log.trace("日志输出:trace信息");
    }
}

Java日志框架JUL、Log4j、logback、log4j2使用_第9张图片
导入Log4j的jar包后测试,报错如下,提示需要添加 appenders。
Java日志框架JUL、Log4j、logback、log4j2使用_第10张图片
按照上面 Log4j 添加 log4j.properties 配置文件配置即可(按需要配置 ConsoleAppender 等 appenders 即可)。
再次测试(在 log4j.properties 配置文件中设置了日志级别是 trace 所以日志都有输出):
Java日志框架JUL、Log4j、logback、log4j2使用_第11张图片
JCL实现日志框架适配的方式:
在JCL内部定义了一个数组,这个数组里面定义的四种就是目前JCL支持的日志实现框架,然后通过循环数组,找到目前项目中有哪些类,从而创建对应日志框架的Logger对象,可以看出来优先级分别是先判断Log4JLogger、Jdk14Logger、Jdk13LumberjackLogger、SimpleLog,只要找到一个实现就返回对应Logger对象,因此JCL本身虽然有个SimpleLog的实现,但是都会被优先级更高的jdk自带的JUL实现(Jdk14Logger、Jdk13LumberjackLogger这两种都是jdk的JUL),同样的项目导入 Log4j 的包之后就会优先实现Log4j。

private static final String[] classesToDiscover =
new String[]{"org.apache.commons.logging.impl.Log4JLogger",
"org.apache.commons.logging.impl.Jdk14Logger",
"org.apache.commons.logging.impl.Jdk13LumberjackLogger",
"org.apache.commons.logging.impl.SimpleLog"};

for(int i = 0; i < classesToDiscover.length && result == null; ++i) {
result = this.createLogFromClass(classesToDiscover[i], logCategory,
true);
}

二、SLF4J

简单日志门面(Simple Logging Facade For Java) SLF4J主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如log4j和logback等;slf4j自己也提供了功能较为简单的实现,但是一般很少用到。对于一般的Java项目而言,日志框架会选择slf4j-api作为门面,配上具体的实现框架(log4j、logback等),中间使用桥接器完成桥接。官网
JCL只支持JUL和Log4j(性能和功能不如logback、log4j2),而SLF4J对于JUL、Log4j 、logback、log4j2都支持,是目前市面上最流行的日志门面。项目中,基本上都是使用SLF4J作为日志门面系统。SLF4J日志门面主要提供两大功能:1. 日志框架的绑定 2. 日志框架的桥接。

slf4j 使用日志实现框架:

  1. 添加slf4j-api的依赖
  2. 绑定具体的日志实现框架
    1. 绑定已经实现了slf4j的日志框架,直接添加对应依赖(slf4j-simple、logback、jul、slf4j-nop遵循slf4j实现)
    2. 绑定没有实现slf4j的日志框架,先添加日志的适配器,再添加实现类的依赖(log4j、log4j2需要导入适配器)
  3. 使用slf4j的API在项目中进行统一的日志记录
  4. slf4j有且仅有一个日志实现框架的绑定(如果出现多个默认使用第一个依赖日志实现)

导入包

        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-apiartifactId>
            <version>1.7.27version>
        dependency>

代码:

package com.test.nexus;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TestSlf4j {
    public static void main(String[] args) {

        Logger logger = LoggerFactory.getLogger(TestSlf4j.class);
        //slf4j没有 fatal 级别的日志
        logger.error("日志输出:error信息");
        logger.warn("日志输出:warn信息");
        logger.info("日志输出:info信息");
        logger.debug("日志输出:debug信息");
        logger.trace("日志输出:trace信息");
        try {
            throw new NullPointerException("空指针!");
        }catch (Exception e){
            logger.error("发生异常:",e);
        }

    }
}

此时只是有日志门面并没有日志实现框架,会报错。
Java日志框架JUL、Log4j、logback、log4j2使用_第12张图片
导入某个具体的日志实现框架。
slf4j-simple slf4j自己实现的简单日志实现框架

        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-simpleartifactId>
            <version>1.7.27version>
        dependency>

Java日志框架JUL、Log4j、logback、log4j2使用_第13张图片
logback

        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-classicartifactId>
            <version>1.2.3version>
        dependency>

如果有多个日志实现框架会出现提示,并默认使用第一个日志框架:
Java日志框架JUL、Log4j、logback、log4j2使用_第14张图片
去除其他日志实现框架,只导入 logback 后:
Java日志框架JUL、Log4j、logback、log4j2使用_第15张图片
jul

        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-jdk14artifactId>
            <version>1.7.27version>
        dependency>

Java日志框架JUL、Log4j、logback、log4j2使用_第16张图片
禁用slf4j日志输出

        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-nopartifactId>
            <version>1.7.27version>
        dependency>

在这里插入图片描述
以上四种日志实现框架因为遵循了 slf4j 的 api 规范,所以导入 slf4j 的包以及这四种日志框架实现包之一后,就可以直接使用。
log4j、log4j2需要做适配。
log4j


        <dependency>
            <groupId>org.slf4jgroupId>
            <artifactId>slf4j-log4j12artifactId>
            <version>1.7.27version>
        dependency>

再导入log4j的包以及配置 log4j.properties 文件,然后测试
Java日志框架JUL、Log4j、logback、log4j2使用_第17张图片
如果测试提示需要配置 appenders ;但已经在 log4j.properties 文件中配置了,那么就将项目 Rebuild 下,再测试。
Java日志框架JUL、Log4j、logback、log4j2使用_第18张图片
注意:很多包里面都包含了一些基础的包,因此某些基础的包可以不用导入;比如使用 slf4j 时需要导入基础包 slf4j-api 但具体的日志实现框架,比如 slf4j-log4j12(适配器)、slf4j-simple、logback-classic、slf4j-nop、slf4j-jdk14等都包含了 slf4j-api 包,因此导入这些日志实现框架后就可以直接使用 slf4j 了。

Spring Boot日志配置

spring boot项目导入的核心包 spring-boot-starter-web 其中已经包含了相关日志门面和日志实现的包,并且spring boot默认是使用SLF4J作为日志门面,logback作为日志实现来记录日志;因此spring boot项目是可以直接使用日志功能的。
Java日志框架JUL、Log4j、logback、log4j2使用_第19张图片
总结:

  1. springboot 底层默认使用logback作为日志实现。
  2. 使用了SLF4J作为日志门面
  3. 将JUL也转换成slf4j
  4. 也可以使用log4j2作为日志门面,但是最终也是通过slf4j调用logback

使用 @Slf4j 注解导入额外两个包 lombok和log4j

        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>

        <dependency>
            <groupId>log4jgroupId>
            <artifactId>log4jartifactId>
            <version>1.2.17version>
        dependency>

编码:

package com.my.test.member.biz.controller;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@Slf4j //@Slf4j注解需要导入两个包(lombok和log4j)才能使用
@RestController
@RequestMapping("testlog")
public class TestLogController {
    final Logger logger = LoggerFactory.getLogger(TestLogController.class);//LoggerFactory不需要导入额外的包就可使用

    @GetMapping("/info/{name}")
    public String info(@PathVariable("name") String name){
        logger.error("日志输出:error信息:"+name);
        logger.warn("日志输出:warn信息:"+name);
        logger.info("日志输出:info信息:"+name);
        logger.debug("日志输出:debug信息:"+name);
        logger.trace("日志输出:trace信息:"+name);

        log.error("日志输出:error信息:"+name+"注解");
        log.warn("日志输出:warn信息:"+name+"注解");
        log.info("日志输出:info信息:"+name+"注解");
        log.debug("日志输出:debug信息:"+name+"注解");
        log.trace("日志输出:trace信息:"+name+"注解");
        return "成功!";
    }

}

Java日志框架JUL、Log4j、logback、log4j2使用_第20张图片
以上都是直接使用默认配置,下面添加日志配置文件:
在resources目录下创建以下配置文件:

日志框架 配置文件
Logback logback-spring.xml 、logback.xml
Log4j2 log4j2-spring.xml 、 log4j2.xml
JUL logging.properties

resources 目录下创建 logback-spring.xml 配置文件:


<configuration>
    
    
    <property name="pattern" value="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} %c %M %L [%thread]  %m%n"/>

    
    <property name="log_dir" value="logs">property>

    
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        
        <target>System.errtarget>
        
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            
            <springProfile name="dev">
                
                <pattern>${pattern}pattern>
            springProfile>
            <springProfile name="pro">
                <pattern>%d{yyyyMMdd:HH:mm:ss.SSS} [%thread] %-5level %msg%n pattern>
            springProfile>
        encoder>
    appender>

    
    <appender name="file" class="ch.qos.logback.core.FileAppender">
        
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}pattern>
        encoder>
        
        <file>${log_dir}/logback.logfile>
    appender>

    
    <appender name="htmlFile" class="ch.qos.logback.core.FileAppender">
        
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.classic.html.HTMLLayout">
                <pattern>%level%d{yyyy-MM-dd HH:mm:ss}%c%M%L%thread%mpattern>
            layout>
        encoder>
        
        <file>${log_dir}/logback.htmlfile>
    appender>

    
    <appender name="rollFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${pattern}pattern>
        encoder>
        
        <file>${log_dir}/roll_logback.logfile>
        
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            
            <fileNamePattern>${log_dir}/rolling.%d{yyyy-MM-dd}-%i.log.gzfileNamePattern>
            
            <maxFileSize>1MBmaxFileSize>
        rollingPolicy>
        
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            
            <level>infolevel>
            
            <onMatch>ACCEPTonMatch>
            
            <onMismatch>DENYonMismatch>
        filter>
    appender>


    
    <root level="info">
        
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
        <appender-ref ref="htmlFile"/>
        <appender-ref ref="rollFile"/>
    root>

configuration>

添加配置文件后可以直接测试,因为 配置文件能被spring boot自动识别,且默认使用 logback 的日志实现。

切换日志实现,项目主流采用 slf4j+log4j2的搭配,那么需要排除 logback 的依赖,spring boot就会自动使用项目中目前存在的日志实现框架。
排除并添加依赖

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
            <exclusions>
                
                <exclusion>
                    <artifactId>spring-boot-starter-loggingartifactId>
                    <groupId>org.springframework.bootgroupId>
                exclusion>
            exclusions>
        dependency>

        
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-log4j2artifactId>
        dependency>
        
        <dependency>
            <groupId>com.lmaxgroupId>
            <artifactId>disruptorartifactId>
            <version>3.3.4version>
        dependency>

resources 目录下创建 logback-spring.xml 配置文件(实现error、warn、info级别日志分开目录及文件记录,AsyncLogger 混合异步日志示例):



<Configuration status="warn" monitorInterval="5">

    <properties>
        
        <property name="LOG_HOME">logsproperty>
    properties>

    <Appenders>
        
        <Console name="Console" target="SYSTEM_OUT">
            
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] [%-5level] %c{36}:%L --- %m%n"/>
        Console>
        
        <File name="file" fileName="${LOG_HOME}/myfile.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
        File>

        
        <RandomAccessFile name="accessFile" fileName="${LOG_HOME}/myAcclog.log">
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %m%n"/>
        RandomAccessFile>

        
        
        <RollingFile name="rollingErrorFile" fileName="${LOG_HOME}/error.log"
                     filePattern="logs/$${date:yyyy-MM-dd}/error/error-%d{yyyy-MM-dd-HH-mm}-%i.log">
            
            
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %msg%n"/>
            
            <Policies>
                
                <OnStartupTriggeringPolicy/>
                
                <SizeBasedTriggeringPolicy size="1MB"/>
                
                <TimeBasedTriggeringPolicy/>
            Policies>
            
            <DefaultRolloverStrategy max="30"/>
        RollingFile>

        
        <RollingFile name="rollingWarnFile" fileName="${LOG_HOME}/warn.log"
                     filePattern="logs/$${date:yyyy-MM-dd}/warn/warn-%d{yyyy-MM-dd-HH-mm}-%i.log">
            
            <Filters>
                
                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
                
                <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
            Filters>
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %msg%n"/>
            
            <Policies>
                
                <OnStartupTriggeringPolicy/>
                
                <SizeBasedTriggeringPolicy size="1MB"/>
                
                <TimeBasedTriggeringPolicy/>
            Policies>
            
            <DefaultRolloverStrategy max="30"/>
        RollingFile>

        
        <RollingFile name="rollingInfoFile" fileName="${LOG_HOME}/info.log"
                     filePattern="logs/$${date:yyyy-MM-dd}/info/info-%d{yyyy-MM-dd-HH-mm}-%i.log">
            
            <Filters>
                
                <ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL"/>
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            Filters>
            <PatternLayout pattern="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %l %c{36} - %msg%n"/>
            
            <Policies>
                
                <OnStartupTriggeringPolicy/>
                
                <SizeBasedTriggeringPolicy size="1MB"/>
                
                <TimeBasedTriggeringPolicy/>
            Policies>
            
            <DefaultRolloverStrategy max="30"/>
        RollingFile>


    Appenders>

    
    <Loggers>
        
        
        <AsyncLogger name="com.my.test.member.biz.controller" level="trace" includeLocation="false" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="rollingErrorFile"/>
            <AppenderRef ref="rollingWarnFile"/>
            <AppenderRef ref="rollingInfoFile"/>
        AsyncLogger>
        
        <Root level="info">
            
            <AppenderRef ref="Console"/>
            <AppenderRef ref="file"/>
            <AppenderRef ref="rollingErrorFile"/>
            <AppenderRef ref="rollingWarnFile"/>
            <AppenderRef ref="rollingInfoFile"/>
        Root>
    Loggers>
Configuration>

在这里插入图片描述

你可能感兴趣的:(日志,java,log4j,logback)