java日志

java中的日志

一 简述:
在Java开发中,常用的日志记录框架有JDK的Log、apache的Log4J、Log4J2、springboot的LogBack、SLF4J。这些日志记录框架各有各的特点,各有各的应用场景。
日志信息根据用途与记录内容的不同分为调试日志、运行日志、异常日志。

日志共有属性

日志级别

为了方便对于日志信息的输出显示,对日志内容进行了分级管理。日志级别由高到低 , 共分 6 个级别:
1.fatal: 指出每个严重的错误事件将会导致应用程序的退出

2.error: 指出虽然发生错误事件,但仍然不影响系统的继续运行

3.warn:	 表明会出现潜在错误的情形

4.info:  在粗粒级别上指明信息,强调应用程序的运行过程

5.debug: 指出细粒级别信息事件,能帮助打印sql

6.、trace(堆栈)

输出指定级别及其更高级别的信息.如指定 info 级别,则会 输出 fatal 、error、warn、info 级别的信息

日志输出控制文件

(1)日志信息的输出位置:控制日志信息将要输出的位置,是控制台还是文件等。
(2)日志信息的输出格式:控制日志信息的显示格式,即以怎样的字符串形式显示。
(3)日志信息的输出级别:控制日志信息的显示内容,即显示哪些级别的日志信息。

日志属性文件由两个对象组成:日志附加器与根日志。
根日志,即为 Java 代码中的日志记录器,其主要由两个属性构成:日志输出级别与日志 附加器。
日志附加器,则由日志输出位置定义,由其它很多属性进行修饰,如输出布局、文件位 置、文件大小等。
在这里插入图片描述
其它类型的日志原理上也是大同小异

定义日志 附加器 appender

所谓日志附加器,就是为日志记录器附加上很多其它设置信息。附加器的本质是一个接 口,其定义语法为:log4j.appender.appenderName = 输出位置
在这里插入图片描述

附加器实现类

ConsoleAppender :日志输出到控制台
FileAppender :日志输出到文件
RollingFileAppender:当日 志文件大小到 达指定尺 寸的 时候将 产生 一 个 新的日志文件
DailyRollingFileAppender:每天产生一个日志文件
这里的是log4j日志的实现类,其它日志均有自己的实现类,功能上大同小异

修饰日志 附加器

所谓修饰日志附加器,就是为定义好的附加器添加一些属性,以控制到指定位置的输出。 不同的附加器,其修饰属性不同。
在这里插入图片描述
File :日志要输出的文件位置及文件名称。 滚动文件附加器:
MaxFileSize :用于指定日志文件的最大值。若文件超过指定值,将自动产生另一个日志 文件。

常用的日志

jdk自带的logger

Logger logger = Logger.getLogger(“类的反射”);
使用非常简单,直接在 JDK 中就可以使用。但 JDKLog 功能比较太过于简单,不支持占位符显示,拓展性比较差,所以现在用的人也很少。

import java.util.logging.Logger;
/****
** JDKLog Demo
**/
public class JDKLog
{
public static void main( String[] args )
{
Logger logger = Logger.getLogger("JDKLog");
logger.info("Hello World.");
}
}

apache的Log4J Log4J2

Log4J 是 Apache 的一个日志开源框架,有多个分级(DEBUG/INFO/WARN/ERROR)记录级别,可以很好地将不同日志级别的日志分开记录,极大地方便了日志的查看。不支持占位符操作,只能用+做字符串的拼接

LogBack

LogBack 其实可以说是 Log4J 的进化版,因为它们两个都是同一个人(Ceki Gülcü)设计的开源日志组件。LogBack 除了具备 Log4j 的所有优点之外,还解决了 Log4J 不能使用占位符的问题。
使用 LogBack 需要首先引入依赖:

LogBack 解决了 Log4J 不能使用占位符的问题,这使得阅读日志代码非常方便。除此之外,LogBack 比 Log4J 有更快的运行速度,更好的内部实现。并且 LogBack 内部集成了 SLF4J 可以更原生地实现一些日志记录的实现。

SLF4J:适配器

上面说了 JDKLog、Log4J、LogBack 这几个常用的日志记录框架,它们都有各自的优缺点,适合在不同的场景下使用。可能简单的项目直接用 JDKLog 就可以了,而复杂的项目需要用上 Log4J。
很多时候我们做项目都是从简单到复杂,也就是我们很可能一开始使用的是 JDKLog,之后业务复杂了需要使用 Log4J,这时候我们如何将原来写好的日志用新的日志框架输出呢?
一个最死板的方法就是一行行代码修改,把之前用 JDKLog 的日志代码全部修改成 Log4J 的日志接口。但是这种方式不仅效率低下,而且做的工作都是重复性的工作,这怎么能忍呢。
正式因为在实际的项目应用中,有时候可能会从一个日志框架切换到另外一个日志框架的需求,这时候往往需要在代码上进行很大的改动。为了避免切换日志组件时要改动代码,这时候一个叫做 SLF4J(Simple Logging Facade for Java,即Java简单日志记录接口集)的东西出现了。
SLF4J(Simple Logging Facade for Java,即Java简单日志记录接口集)是一个日志的接口规范,它对用户提供了统一的日志接口,屏蔽了不同日志组件的差异。
这样我们在编写代码的时候只需要看 SLF4J 这个接口文档即可,不需要去理会不同日之框架的区别。而当我们需要更换日志组件的时候,我们只需要更换一个具体的日志组件Jar包就可以了。
而整合 SLF4J 和日志框架使用也是一件很简单的事情。

springboot日志配置

上面的信息了解即可,下面才是我们主要讲解的springboot的配置

当下流行框架SLF4J + LogBack实例

注: springbott父模块起步依赖中都已经有了这两个jar包,所以springboot最好是用SLF4J + LogBack作为日志框架
优势:
LogBack 自身实现了 SLF4J 的日志接口,不需要 SLF4J 去做进一步的适配。
LogBack 自身是在 Log4J 的基础上优化而成的,其运行速度和效率都比 LOG4J 高。
SLF4J + LogBack 支持占位符,方便日志代码的阅读,而 LOG4J 则不支持。
LogBack 被分为3个组件:logback-core、logback-classic 和 logback-access。
logback-core 提供了 LogBack 的核心功能,是另外两个组件的基础。
logback-classic 则实现了 SLF4J 的API,所以当想配合 SLF4J 使用时,需要将 logback-classic 引入依赖中。
logback-access 是为了集成Servlet环境而准备的,可提供HTTP-access的日志接口。
LogBack的日志记录数据流是从 Class(Package)到 Logger,再从Logger到Appender,最后从Appender到具体的输出终端。

默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台。在运行应用程序和其他例子时,你应该已经看到很多INFO级别的日志了。
在这里插入图片描述
从上图可以看到,日志输出内容元素具体如下:
时间日期:精确到毫秒
日志级别:ERROR, WARN, INFO, DEBUG or TRACE
进程ID
分隔符:— 标识实际日志的开始
线程名:方括号括起来(可能会截断控制台输出)
Logger名:通常使用源代码的类名
日志内容
注: 也就是说即使我们不添加logback配置文件,springboot也会默认控制台输出INFO级别的信息(带颜色),不会写到日志文件,这样太过鸡助.
这样的话咱们可以使用.yaml配置文件简单配置想要打印sql信息的dao接口包为debug
不过这种通过主配置文件设置日志或引入日志的方式不建议应用,灵活性小

logging:
  level:
  	#Dao接口的包,不可以使用*通用找包
    com.guojianquan.mapper: debug
    org.thymeleaf: info
    #若是配置了这个引入文件那么上面的com.guojianquan.mapper: debug无效
  config: classpath:logback.xml
添加日志依赖
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-logging</artifactId>
</dependency>

但是呢,实际开发中我们不需要直接添加该依赖。
你会发现 spring-boot-starter 其中包含了 spring-boot-starter-logging ,该依赖内容就是 Spring Boot 默认的日志框架 logback 。工程中有用到了 Thymeleaf ,而 Thymeleaf 依赖包含了 spring-boot-starter ,最终我只要引入 Thymeleaf 即可。

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
引入自定义日志配置文件

springboot能根据你的有规则的日志名称自动引入配置文件,而不需要再主配置yaml文件中引入:

Logback: logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
Log4j: log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
Log4j2: log4j2-spring.xml, log4j2.xml
JDK (Java Util Logging): logging.properties

Spring Boot 官方推荐优先使用带有 -spring 的文件名作为你的日志配置(如使用 logback-spring.xml ,而不是 logback.xml ),命名为 logback-spring.xml 的日志配置文件, spring boot 可以为它添加一些 spring boot 特有的配置项

默认的命名规则,并且放在 src/main/resources 下面即可
如果你即想完全掌控日志配置,但又不想用 logback.xml 作为 Logback 配置的名字, application.yml 可以通过 logging.config 属性指定自定义的名字:

logging.config=classpath:logging-config.xml

虽然一般并不需要改变配置文件的名字,但是如果你想针对不同运行时 Profile 使用不同的日志配置,这个功能会很有用。
一般不需要这个属性,而是直接在 logback-spring.xml 中使用 springProfile 配置,不需要 logging.config 指定不同环境使用不同配置文件(这是根据测试 上线日志需求做的)

控制台输出

日志级别从低到高分为:

TRACE < DEBUG < INFO < WARN < ERROR < FATAL 

如果设置为 WARN ,则低于 WARN 的信息都不会输出。
Spring Boot 中默认配置 ERROR 、 WARN 和 INFO 级别的日志输出到控制台

代码中引用
private static Logger log = LoggerFactory.getLogger(LogbackDemo.class);  

如果每次都写这行代码会很麻烦,可以使用注解,但是需要使用 lombok :
添加依赖:
//注解
compile ‘org.projectlombok:lombok:1.16.18’
安装 lombok 的插件:
Go to File > Settings > Plugins
Click on Browse repositories…
Search for Lombok Plugin
Click on Install plugin
Restart Android Studio

允许注解处理,Settings -> Compiler -> Annotation Processors
在这里插入图片描述
可以使用 {} 占位符来拼接字符串,而不需要使用 ““+”” 来连接字符串。
这个是log4j2不支持的

logback节点分析
1 根节点包含的属性

scan:当此属性设置为 true 时,配置文件如果发生改变,将会被重新加载,默认值为 true 。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当 scan 为 true 时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为 true 时,将打印出 logback 内部日志信息,实时查看 logback 运行状态。默认值为 false 。

2设置变量:

用来定义变量值的标签, 有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。

<?xml version="1.0" encoding="utf-8"?>
<configuration debug="true">
    <property name="PROJECT" value="gjqlogs"/>
    <!--定义日志文件的存储地址,勿在logBack的配置中使用相对路径-->
    <property name="ROOT" value="e:/${PROJECT}/"/>
    <!--日志文件最大的大小-->
    <property name="FILESIZE" value="50MB"/>
    <!--日志保留天数-->
    <property name="MAXHISTORY" value="100"/>

<!--ERROR 输入到文件,按日期和文件大小-->
    <!--RollingFileAppender 按照每天生成日志文件-->
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <fileNamePattern>${ROOT}%d/error.%i.log</fileNamePattern>
            <!--日志保留天数-->
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
3设置root

也是元素,但是它是根loger。只有一个level属性,应为已经被命名为"root".
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为INHERITED或者同义词NULL。默认是DEBUG。
可以包含零个或多个元素,标识这个appender将会添加到这个loger。
这个里面配置的是让你定义的那些启动
root 里面自带的level 设置日志级别一把会省略,因为项目中最好每一个appender里面都有个级别过滤器(每一个appender里面定义的是细化的输出位置 输出级别)

4 设置loger

用来设置某一个包或者具体的某一个类的日志打印级别、以及指定 。 仅有一个 name 属性,一个可选的 level 和一个可选的 addtivity 属性。
name :用来指定受此loger约束的某一个包或者具体的某一个类不能出现通用*。
level :用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前loger将会继承上级的级别。
addtivity :是否向上级loger传递打印信息。默认是true。如果单独设置了loger且引入了自己定义的,则addtivity属性最好false不传给根loger代表标签中引入的那些引用

loger在实际使用的时候有两种情况
举例说明-demo

package logback;  
  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
  
public class LogbackDemo {  
    private static Logger log = LoggerFactory.getLogger(LogbackDemo.class);  
    public static void main(String[] args) {  
        log.trace("======trace");  
        log.debug("======debug");  
        log.info("======info");  
        log.warn("======warn");  
        log.error("======error");  
    }  
}

logback.xml配置文件
第1种:只配置root:

<configuration>   
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">   
    <!-- encoder 默认配置为PatternLayoutEncoder -->   
    <encoder>   
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>   
    </encoder>   
  </appender>   
  <root level="INFO">             
    <appender-ref ref="STDOUT" />   
  </root>       
 </configuration>

其中appender的配置表示打印到控制台
将root的打印级别设置为“INFO”,指定了名字为“STDOUT”的appender。
当执行logback.LogbackDemo类的main方法时,root将级别为“INFO”及大于“INFO”的日志信息交给已经配置好的名为“STDOUT”的appender处理,“STDOUT”appender将信息打印到控制台;

打印结果如下:

13:30:38.484 [main] INFO  logback.LogbackDemo - ======info  
13:30:38.500 [main] WARN  logback.LogbackDemo - ======warn  
13:30:38.500 [main] ERROR logback.LogbackDemo - ======error

第2种:带有loger的配置,不指定级别,不指定appender

<configuration>   
   
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">   
    <!-- encoder 默认配置为PatternLayoutEncoder -->   
    <encoder>   
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>   
    </encoder>   
  </appender>   
   
  <!-- logback为java中的包 -->   
  <logger name="logback"/>   
  <root level="DEBUG">             
    <appender-ref ref="STDOUT" />   
  </root>        
 </configuration>

其中appender的配置表示打印到控制台
将控制logback包下的所有类的日志的打印,但是并没用设置打印级别,所以继承他的上级的日志级别“DEBUG”;
没有设置addtivity,默认为true,将此loger的打印信息向上级传递;
没有设置appender,此loger本身不打印任何信息。
将root的打印级别设置为“DEBUG”,指定了名字为“STDOUT”的appender。

当执行logback.LogbackDemo类的main方法时,因为LogbackDemo 在包logback中,所以首先执行,将级别为“DEBUG”及大于“DEBUG”的日志信息传递给root,本身并不打印;
root接到下级传递的信息,交给已经配置好的名为“STDOUT”的appender处理,“STDOUT”appender将信息打印到控制台;

打印结果如下:

13:19:15.406 [main] DEBUG logback.LogbackDemo - ======debug  
13:19:15.406 [main] INFO  logback.LogbackDemo - ======info  
13:19:15.406 [main] WARN  logback.LogbackDemo - ======warn  
13:19:15.406 [main] ERROR logback.LogbackDemo - ======error

第3种:带有多个loger的配置,指定级别,指定appender

<configuration>   
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">   
    <!-- encoder 默认配置为PatternLayoutEncoder -->   
    <encoder>   
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>   
    </encoder>   
  </appender>   
   
  <!-- logback为java中的包 -->   
  <logger name="logback"/>   
  <!--logback.LogbackDemo:类的全路径 -->   
  <logger name="logback.LogbackDemo" level="INFO" additivity="false"><name对应的就是dao包 切记不能带有*>  
    <appender-ref ref="STDOUT1"/><自己单独为控制台定义的aappender,让控制台能执行sal的时候打印>  
  </logger>   
    
  <root level="DEBUG">             
    <appender-ref ref="STDOUT" />   
  </root>     
</configuration>

将控制logback包下的所有类的日志的打印,但是并没用设置打印级别,所以继承他的上级的日志级别“DEBUG”;
没有设置addtivity,默认为true,将此loger的打印信息向上级传递;
没有设置appender,此loger本身不打印任何信息。

控制logback.LogbackDemo类的日志打印,打印级别为“INFO”;
additivity属性为false,表示此loger的打印信息不再向上级传递,
指定了名字为“STDOUT”的appender。
将root的打印级别设置为“DEBUG”,指定了名字为“STDOUT”的appender。

当执行logback.LogbackDemo类的main方法时,先执行,将级别为“INFO”及大于“INFO”的日志信息交给此loger指定的名为“STDOUT”的appender处理,在控制台中打出日志,不再向次loger的上级 传递打印信息;
未接到任何打印信息,当然也不会给它的上级root传递任何打印信息;

打印结果如下:

14:05:35.937 [main] INFO  logback.LogbackDemo - ======info  
14:05:35.937 [main] WARN  logback.LogbackDemo - ======warn  
14:05:35.937 [main] ERROR logback.LogbackDemo - ======error

如果将修改为 那打印结果将是什么呢?
没错,日志打印了两次,想必大家都知道原因了,因为打印信息向上级传递,logger本身打印一次,root接到后又打印一次

打印结果如下:

 14:09:01.531 [main] INFO  logback.LogbackDemo - ======info  
14:09:01.531 [main] INFO  logback.LogbackDemo - ======info  
14:09:01.531 [main] WARN  logback.LogbackDemo - ======warn  
14:09:01.531 [main] WARN  logback.LogbackDemo - ======warn  
14:09:01.531 [main] ERROR logback.LogbackDemo - ======error  
14:09:01.531 [main] ERROR logback.LogbackDemo - ======error
5 appender节点

用来格式化日志输出节点,有俩个属性name和class,class用来指定哪种输出策略,常用就是控制台输出策略和文件输出策略。
ch.qos.logback.core.ConsoleAppender 控制台输出
ch.qos.logback.core.FileAppender 文件输出
ch.qos.logback.core.RollingFileAppender 文件滚动输出(日志分割)
ConsoleAppender
把日志添加到控制台,有如下节点:
: 对日志进行格式化。
: 字符串System.out 或者 System.err, 默认 System.out;

样例子:

<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <!-- 正在记录的日志文件的路径及文件名 -->
    <file>${log.path}/log_info.log</file>
    <!--日志文件输出格式-->
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
    <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- 每天日志归档路径以及格式,编码器 -->
        <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
        <!--每个文件最多100MB-->
        <maxFileSize>100MB</maxFileSize>
        <!--日志文件保留天数可以省略-->
        <maxHistory>15</maxHistory>
        <!--每个文件最多100MB,保留15天的历史记录,但最多20GB-->
        <totalSizeCap>20GB</totalSizeCap>
        <!--重启清理日志文件可以省略-->
        <cleanHistoryOnStart>true</cleanHistoryOnStart>
    </rollingPolicy>
    <!-- 此日志文件只记录info级别的 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>info</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
</appender>
ConsoleAppender控制台输出

示例一:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
 <contextName>logback-demo</contextName>
 <!--输出到控制台 ConsoleAppender-->
 <appender name="consoleLog1" class="ch.qos.logback.core.ConsoleAppender">
 <!--展示格式 layout-->
 <layout class="ch.qos.logback.classic.PatternLayout">
  <pattern>%d -1 %msg%n</pattern>
 </layout>
 </appender>
 <!--输出到控制台 ConsoleAppender-->
 <appender name="consoleLog2" class="ch.qos.logback.core.ConsoleAppender">
 <encoder>
  <pattern>%d -2 %msg%n</pattern>
 </encoder>
 </appender>
 <!--指定最基础的日志输出级别-->
 <root level="INFO">
 <!--appender将会添加到这个loger-->
 <appender-ref ref="consoleLog1"/>
 <appender-ref ref="consoleLog2"/>
 </root>
</configuration>

可以看到 layout 和 encoder ,都可以将事件转换为格式化后的日志记录,但是控制台输出使用 layout ,文件输出使用 encoder 。
表示对日志进行编码:
%d{HH: mm:ss.SSS}——日志输出时间
%thread——输出日志的进程名字,这在Web应用以及异步任务处理中很有用
%-5level——日志级别,并且使用5个字符靠左对齐
%logger{36}——日志输出者的名字
%msg——日志消息
%n——平台的换行符

示例2:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
 <contextName>logback-demo</contextName>
 <!--输出到控制台 ConsoleAppender-->
 <appender name="consoleLog1" class="ch.qos.logback.core.ConsoleAppender">
 <!--展示格式 layout-->
 <layout class="ch.qos.logback.classic.PatternLayout">
  <pattern>
  <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
  </pattern>
 </layout>
 <!--
 <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
  <level>ERROR</level>
 </filter>
  -->
 </appender>
 <!--指定最基础的日志输出级别-->
 <root level="INFO">
 <!--appender将会添加到这个loger-->
 <appender-ref ref="consoleLog1"/>
 <appender-ref ref="consoleLog2"/>
 </root>
</configuration>

ThresholdFilter为系统定义的拦截器,例如我们用ThresholdFilter来过滤掉ERROR级别以下的日志不输出到文件中。如果不用记得注释掉,不然你控制台会发现没日志~
也可以用

    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>ERROR</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>

替代

RollingFileAppender切分文件日志
<?xml version="1.0" encoding="utf-8"?>
<configuration debug="true">
    <property name="PROJECT" value="gjqlogs"/>
    <!--定义日志文件的存储地址,勿在logBack的配置中使用相对路径-->
    <property name="ROOT" value="e:/${PROJECT}/"/>
    <!--日志文件最大的大小-->
    <property name="FILESIZE" value="50MB"/>
    <!--日志保留天数-->
    <property name="MAXHISTORY" value="100"/>

    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <encoder charset="utf-8">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!--ERROR 输入到文件,按日期和文件大小-->
    <!--RollingFileAppender 按照每天生成日志文件-->
    <appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
    	<!--日志输出编码格式化-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level><!--只要ERROR级别的日志符合就输出-->
            <onMatch>ACCEPT</onMatch> <!--匹配-->
            <onMismatch>DENY</onMismatch><!--没有匹配禁止-->
        </filter>
        
		<!--日志名称,如果没有File 属性,那么只会使用FileNamePattern的文件路径规则
 如果同时有<File>和<FileNamePattern>,那么当天日志是<File>,明天会自动把今天
 的日志改名为今天的日期。即,<File> 的日志都是当天的。
 -->
 		<File>${logback.logdir}/info.${logback.appname}.log</File>
 		<!--滚动策略,按照时间滚动 TimeBasedRollingPolicy-->
 		<!--文件路径,定义了日志的切分方式——把每一天的日志归档到一个文件中,以防止日志填满整个磁盘空间-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <fileNamePattern>${ROOT}%d/error.%i.log</fileNamePattern>
            <!--日志保留天数-->
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
			<!--用来指定日志文件的上限大小,那么到了这个值,就会删除旧的日志-->
 			<!--<totalSizeCap>1GB</totalSizeCap>-->
        </rollingPolicy>
    </appender>

    <!--WARN 输入到文件,按日期和文件大小-->
    <!--RollingFileAppender 按照每天生成日志文件-->
    <appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <fileNamePattern>${ROOT}%d/warn.%i.log</fileNamePattern>
            <!--日志保留天数-->
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>

    <!--DEBUG 输入到文件,按日期和文件大小-->
    <!--RollingFileAppender 按照每天生成日志文件-->
    <appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <fileNamePattern>${ROOT}%d/debug.%i.log</fileNamePattern>
            <!--日志保留天数-->
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>

    <!--INFO 输入到文件,按日期和文件大小-->
    <!--RollingFileAppender 按照每天生成日志文件-->
    <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <fileNamePattern>${ROOT}%d/info.%i.log</fileNamePattern>
            <!--日志保留天数-->
            <maxHistory>${MAXHISTORY}</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${FILESIZE}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>

    <logger name="com.guojianquan.mapper.gjqmapper" level="DEBUG"></logger>

    <!--Logger 根目录-->
    <!--日志输出级别-->
    <root level="DEBUG">
        <!-- appender-ref标识这个appender将会添加到本应用的日志系统中 -->
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="INFO"/>
        <appender-ref ref="DEBUG"/>
        <appender-ref ref="ERROR"/>
        <appender-ref ref="WARN"/>
    </root>

</configuration>

如果同时有 和 ,根据日期分割日志,代码注释写的很清楚了。
在这里插入图片描述
如果要区分 Info 和 Error 级别的日志,那么需要使用过滤规则的策略,代码注释写的很清楚了。

maxHistory

可选的 maxHistory 属性控制要保留的归档文件的最大数量,以异步方式删除较旧的文件。例如,如果您指定每月滚动,并将maxHistory设置为6,则将保留6个月的归档文件,并删除6个月以上的文件。请注意,由于删除了旧的归档日志文件,因此将适当删除为日志文件归档而创建的所有文件夹。

totalSizeCap

可选的totalSizeCap 属性控制所有存档文件的总大小。当超过总大小上限时,最早的档案将被异步删除。该totalSizeCap属性要求maxHistory属性设置为好。此外,始终会首先应用“最大历史记录”限制,然后再应用“总大小上限”限制。

cleanHistoryOnStart

如果设置为true,则将在追加程序启动时执行归档删除。默认情况下,此属性设置为false。
通常在过渡期间执行归档删除。但是,某些应用程序的生存时间可能不足以触发翻转。因此,对于这种短暂的应用程序,归档删除可能永远不会有执行的机会。通过将cleanHistoryOnStart设置为true,将在附加程序启动时执行归档删除。
在这里插入图片描述

fileNamePattern 值及其作用说明
6FileAppender

把日志添加到文件,有如下节点:
:被写入的文件名,可以是相对目录 , 也可以是绝对目录 , 如果目录不存在则会自动创建。
:如果是true , 日志被追加到文件结尾 , 如果是false,清空现存文件 , 默认是true。
:对日志进行格式化 [具体的转换符说明请参见官网.]

<?xml version="1.0" encoding="utf-8"?>
<configuration>
	<appender name="file_out" class="ch.qos.logback.core.FileAppender">
		<file>logs/debug.log</file>
		<encoder>
		<pattern>%date [%thread] %-5level %logger - %message%newline</pattern>
		</encoder>
	</appender>
</configuration>

7rollingFileAppender

滚动记录文件,先将日志记录到指定文件,当符合某种条件时,将日志记录到其他文件,有如下节点:
:被写入的文件名,可以是相对目录,也可以解决目录,如果目录不存在则自动创建。
:如果是true,日志被追加到文件结尾,如果是false,清空现存文件,默认是true。
:对日志进行格式化。
:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。
rollingPolicy
TimeBaseRollingPolicy :最常用的滚动策略,根据时间来制定滚动策略,即负责滚动也负责触发滚动。有如下节点;
:必要节点,包含文件及“%d” 转换符,“%d”可以包含一个java.text.SimpleDateFormat 制定的时间格式,如:%d{yyyy-MM},如果直接使用%d ,默认格式是 yyyy-MM-dd。
:可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件,假设设置每个月滚动,且 是 6,则只保存最近6个月的文件,删除之前的旧文件,注意:删除旧文件是哪些为了归档而创建的目录也会被删除。
:必须包含“%i” 例如:设置最小值,和最大值分别为1和2,命名模式为 log%i.log,会产生归档文件log1.log和log2.log,还可以指定文件压缩选项,例如:log%i.log.gz 或者 log%i.log.zip
triggeringPolicy:告知RollingFileAppender,激活RollingFileAppender滚动。

<!-- 03:conf errorAppender out -->
<appender name="errorAppender" class="ch.qos.logback.core.RollingFileAppender">
<file>logs/error.log</file>
<!-- 设置滚动策略 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--设置日志命名模式-->
<fileNamePattern>errorFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!--最多保留30天log-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<!-- 超过150MB时,触发滚动策略 -->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>150</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d [%p] %-5level %logger - %msg%newline</pattern>
</encoder>
</appender>

8filter过滤节点

级别过滤器(LevelFilter)
LevelFilter 根据记录级别对记录事件进行过滤。如果事件的级别等于配置的级别,过滤 器会根据 onMatch 和 onMismatch 属性接受或拒绝事件。下面是个配置文件例子:

9多环境日志输出
<configuration>
 ...
 <!-- 测试环境+开发环境. 多个使用逗号隔开. -->
 <springProfile name="test,dev">
 <logger name="com.example.demo.controller" level="DEBUG" additivity="false">
  <appender-ref ref="consoleLog"/>
 </logger>
 </springProfile>
 <!-- 生产环境. -->
 <springProfile name="prod">
 <logger name="com.example.demo.controller" level="INFO" additivity="false">
  <appender-ref ref="consoleLog"/>
 </logger>
 </springProfile>
</configuration>

application.yml 增加环境选择的配置

server:
port: 9010

spring:
profiles:
active: dev
active: 【test、dev、prod】 ,根据 active 的环境,自动采用上面配置的 springProfile 的 logger 日志

logback使用占位符操作
private static final Logger log = LoggerFactory.getLogger(ExceptionControllerAdvice.class);
log.info("id:{},name:{},ip:{},url:{},params:{}",
参数1,
参数2,
参数3,
参数4,
参数5);
如何进行日志系统转换?

在实际的日志转换过程中,SLF4J其实是充当了一个中介的角色。例如当我们一个项目原来是使用LOG4J进行日志记录,但是我们要换成LogBack进行日志记录。
此时我们需要先将LOG4J转换成SLF4J日志系统,再从SLF4J日志系统转成LogBack日志系统。
从日志框架转向SLF4J
jul-to-slf4j:jdk-logging到slf4j的桥梁
log4j-over-slf4j:log4j1到slf4j的桥梁
jcl-over-slf4j:commons-logging到slf4j的桥梁
从SLF4J转向具体的日志框架
slf4j-jdk14:slf4j到jdk-logging的桥梁
slf4j-log4j12:slf4j到log4j1的桥梁
log4j-slf4j-impl:slf4j到log4j2的桥梁
logback-classic:slf4j到logback的桥梁
slf4j-jcl:slf4j到commons-logging的桥梁
例如我们一开始使用的是 Log4J 日志框架,现在我们希望转成 LogBack 框架,那么我们首先需要加入 log4j-over-slf4j.jar 将 Log4J 转成 SLF4J,之后再加入 logback-classic.jar 将 SLF4J 转成 LogBack。

日志技术框架一览

JUL:JDK中的日志记录工具,也常称为JDKLog、jdk-logging。
LOG4J1:一个具体的日志实现框架。
LOG4J2:一个具体的日志实现框架,是LOG4J1的下一个版本。
LOGBACK:一个具体的日志实现框架,但其性能更好。
JCL:一个日志门面,提供统一的日志记录接口,也常称为commons-logging。
SLF4J:一个日志门面,与JCL一样提供统一的日志记录接口,可以方便地切换看具体的实现框架。
JUL、LOG4J1、LOG4J2、LOGBACK是日志实现框架,而JCL、SLF4J是日志实现门面

总结:

1 springboot 中默认引入了logback SLF4J 所需要的maven依赖
2 如果不配置logback-spring.xml springboot默认是控制台输出INFO信息 而不会创建文件日志
3 springboot 能自动阴日 resources 下的 logback-spring.xml 名称的文件 不需要主配置文件.yam中引入
4 主配置文件.yam可以在没有logback-spring.xml配置文件情况下做些简单的日志配置(仅仅是简单),同时它也能帮助我们引入loaback-spring.xml日志配置 不过日志文件名称不要 以loaback.xml logback-spring.xml 任意文字-spring.xml 这样命名,因为springboot会把这样的文件又重新引入一遍,消耗内存
5 主配置文件.yaml引入logback日志配置文件的场景都是用于区别不同环境下引入的日志文件(测试 正式 发布),如果引入了日志配置文件则yam.xml其它如设置包日志级别之类的配置会失效,以引入日志配置文件中的配置为主.
6是定义日志附加器的,常规操作:一个日志文件中会有好几个日志附加器,具体看自己的需求,如控制台输出级别为INFO的日志附加器 文件输出级别为Error的日志附加器 文件输出级别为INFO的日志附加器 文件输出日志级别为debug的日志附加器 自己定义的一个控制台输出级别为debug的日志附加器
7 日志输出级别debug的可以在控制台或者文件中输出sql语句 细力度 信息量很多,所以一般控制台日志附加器为INFO 咱们自己定义几个针对doMapper接口的包 控制台输出级别为debug的日志附加器,用标签引入
8 属于根loger,它会把引入的日志附加器启动,也就是说我们自己定义的那些日志附加器如果想要启动,只能在中引入 或者 在中引入
9 和都能引入日志附加器,不过属于根loger, 控制全局的作用. 的应用只是为了把想要的那一小部分需要打印sql的doMapper 设置debug 在控制台打印sql 如果addtivity 没有设着为false 它里面的引入的日志附加器会自动在中引入 从而打印两边日志信息
10 中都有 lever设置输出级别的全局控制,这样控制未免太过死板,不灵活,一般我们都会在每个日志附加器中配置好过滤输出级别方便让 引入的时候不需要添加lever过滤级别

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值